| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 |
- CICD
- openAI API
- 프리티어
- 스프링부트
- Redis
- 생활코딩
- bastion host
- 캡스톤디자인프로젝트
- UNIDEV
- 백엔드개발자
- NAT gateway
- 전국대학생게임개발동아리연합회
- 오블완
- 개발공부
- EC2
- 티스토리챌린지
- 라피신
- 체크인미팅
- 프로그래밍
- Route53
- AWS
- 도커
- 인프라
- UNICON2023
- 게임개발동아리
- 42서울
- UNICON
- 프롬프트엔지니어링
- spring ai
- Spring boot
- Today
- Total
Hyun's Wonderwall
[백준 골드2] 1781번: 컵라면 (우선순위 큐, 그리디) - Java 본문
"스파르타코딩클럽 작심큰일 챌린지" 3일차 챌린저 문제
1781번: 컵라면
https://www.acmicpc.net/problem/1781
문제
상욱 조교는 동호에게 N개의 문제를 주고서, 각각의 문제를 풀었을 때 컵라면을 몇 개 줄 것인지 제시 하였다. 하지만 동호의 찌를듯한 자신감에 소심한 상욱 조교는 각각의 문제에 대해 데드라인을 정하였다.
문제 번호 1 2 3 4 5 6 7
데드라인 1 1 3 3 2 2 6
컵라면 수 6 7 2 1 4 5 1
위와 같은 상황에서 동호가 2, 6, 3, 1, 7, 5, 4 순으로 숙제를 한다면 2, 6, 3, 7번 문제를 시간 내에 풀어 총 15개의 컵라면을 받을 수 있다.
문제는 동호가 받을 수 있는 최대 컵라면 수를 구하는 것이다. 위의 예에서는 15가 최대이다.
문제를 푸는데는 단위 시간 1이 걸리며, 각 문제의 데드라인은 N이하의 자연수이다. 또, 각 문제를 풀 때 받을 수 있는 컵라면 수와 최대로 받을 수 있는 컵라면 수는 모두 231보다 작은 자연수이다.
입력
첫 줄에 숙제의 개수 N (1 ≤ N ≤ 200,000)이 들어온다. 다음 줄부터 N+1번째 줄까지 i+1번째 줄에 i번째 문제에 대한 데드라인과 풀면 받을 수 있는 컵라면 수가 공백으로 구분되어 입력된다.
출력
첫 줄에 동호가 받을 수 있는 최대 컵라면 수를 출력한다.
예제 입력 1
7
1 6
1 7
3 2
3 1
2 4
2 5
6 1
예제 출력 1
15
알고리즘: 자료 구조, 그리디 알고리즘, 우선순위 큐
풀이
같은 시간이라면 높은 보상을 선택해야 하므로 우선 순위 구조가 필요해 우선 순위 큐를 사용했다. 매 순간 최적의 선택을 해야 하기 때문에 그리디 알고리즘이다.
시도
데드라인과 보상으로 지급되는 컵라면 수가 쌍을 이루는 점 때문에 PriorityQueue에 쌍을 저장하고 정렬을 통해 풀으려고 했는데, 그렇게 해버렸더니 아래의 테스트 케이스를 통과하지 못했다.
2
1 25
2 50
2 100
오답: 125 / 정답: 150
GPT에게 물어보니 유니온파인드를 하면 문제가 풀리게 할 수는 있다는 것을 알게 되었지만... 이렇게 그래프화해서 푸는 걸 의도한 문제는 아닌 것 같았다.
아래는 유니온 파인드 풀이:
import java.io.*;
import java.util.*;
public class Main {
static int[] parent;
static int find(int x) {
if (parent[x] == x)
return x;
return parent[x] = find(parent[x]);
}
static void union(int x, int y) {
parent[find(x)] = find(y);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
PriorityQueue<int[]> pq = new PriorityQueue<>((a, b) -> {
if (a[1] != b[1]) return Integer.compare(b[1], a[1]);
else return Integer.compare(a[0], b[0]);
});
int maxTime = 0;
for (int i = 0; i < n; i++) {
String[] s = br.readLine().split(" ");
int d = Integer.parseInt(s[0]);
int r = Integer.parseInt(s[1]);
pq.offer(new int[]{d, r});
if (d > maxTime) maxTime = d;
}
parent = new int[maxTime+2];
for (int i=0; i<=maxTime+1; i++)
parent[i] = i;
int sum = 0;
while (!pq.isEmpty()) {
int[] curr = pq.poll();
int available = find(curr[0]);
if (available == 0) // 0인 경우 불가능
continue;
sum += curr[1];
union(available, available-1);
}
System.out.println(sum);
}
}
아래는 작심큰일 챌린지의 모범답안을 참고해 우선순위 큐와 그리디만으로 푼 풀이이다.
Problem 클래스에서 Comparable 인터페이스를 구현하고 compareTo 메소드를 오버라이딩해 deadline 오름차순 정렬*을 설정했다.
(*-를 사용해서 음수이면 오름차순; 문제 범위 상 오버플로우 x. Integer.compare(this.deadline, o.deadline)와 같다.)
List에 Problem 객체를 담고 정렬한 후 하나씩 꺼내면서 우선순위 큐에 넣는데, 우선순위 큐의 크기 > 객체 p.deadline이면 pq.poll 해서 가장 적은 컵라면 수(의 문제를 푸는 경우)를 버린다.
+) Java에서 PriorityQueue는 min-heap(최소 힙)으로 동작한다. (큐에서 가장 작은 값이 항상 맨 앞에 위치)
+) max-heap을 쓸 경우 PriorityQueue<Integer> pq = new PriorityQueue<>(Collections.reverseOrder());와 같이 선언한다.
import java.io.*;
import java.util.*;
public class Main {
static class Problem implements Comparable<Problem> {
int deadline;
int ramen;
Problem(int deadline, int ramen) {
this.deadline = deadline;
this.ramen = ramen;
}
@Override
public int compareTo(Problem o) {
return this.deadline - o.deadline;
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
List<Problem> problems = new ArrayList<>();
for (int i=0; i<n; i++) {
StringTokenizer st = new StringTokenizer(br.readLine());
int d = Integer.parseInt(st.nextToken());
int r = Integer.parseInt(st.nextToken());
problems.add(new Problem(d, r));
}
Collections.sort(problems);
PriorityQueue<Integer> pq = new PriorityQueue<>();
for (Problem p : problems) {
pq.offer(p.ramen);
if (pq.size() > p.deadline) {
pq.poll();
}
}
long count = 0;
for (int r : pq)
count += r;
System.out.println(count);
}
}
'Study > PS' 카테고리의 다른 글
| [백준 실버3] 14501번: 퇴사 (DP) - Java (3) | 2025.08.17 |
|---|---|
| [백준 골드2] 1103번: 게임 (DP, DFS) - Java (2) | 2025.08.17 |
| [백준 골드1] 1450번: 냅색문제 (이분탐색, 중간에서 만나기) - Java (4) | 2025.08.06 |
| [백준 골드1] 16118번: 달빛 여우 (다익스트라) - Java (4) | 2025.08.04 |
| [백준 골드4] 1715번: 카드 정렬하기 (우선순위 큐) - Java (4) | 2025.08.02 |