그리디의 단골문제이다. 기한이 정해져 있고 최대의 이득을 취하는 그리디 알고리즘의 취지에 딱 맞는 문제다.
이런 문제는 어떤 기준으로 정렬기준이 굉장히 중요하다. 처음에 생각한 기준은
1순위 : 기한이 촉박한 것
2순위 : 기한이 같다면 페이가 센 것
그렇게 해서 완성했던 코드이다.
import java.util.*;
import java.io.*;
public class Main
{
static class node implements Comparable<node>
{
int p;
int d;
public node(int p, int d)
{
this.p = p;
this.d = d;
}
public int compareTo(node n) //우선 기한이 촉박한 것부터, 같다면 페이가 센 걸로
{
if(d == n.d) return n.p - p;
else return d - n.d;
}
}
static long ans;
static int n, day;
static PriorityQueue<node> pq;
public static void main (String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
n = Integer.parseInt(br.readLine());
pq = new PriorityQueue<>();
for(int i = 0 ; i < n ; i++)
{
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
pq.add(new node(a,b));
}
while(!pq.isEmpty())
{
node nod = pq.poll();
if(day < nod.d)
{
day++;
ans += nod.p;
}
}
System.out.println(ans);
}
}
테스트 케이스는 통과했으나, 반례를 뚫지 못했다.
20
85 8
56 11
58 12
28 20
36 12
45 9
55 4
1 3
71 6
72 15
38 9
76 20
67 5
78 2
48 18
100 3
16 2
7 10
95 5
42 14
answer : 1050
역으로 최대 기한에서 타고 올라가는 방식도 생각했는데, 별반 다를 것 없어서 포기했다.
그래서 기준을 다르게 바꿨는데
1순위 : 페이가 센 것
2순위 : 같다면 기한이 촉박한 것
우선순위가 역전이 되었고 감정이입해 스케쥴 표에 작성하듯이 배열에다가 정리도 해줬다.
<문제>
https://www.acmicpc.net/problem/2109
<소스코드>
import java.util.*;
import java.io.*;
public class Main
{
static class node implements Comparable<node>
{
int p;
int d;
public node(int p, int d)
{
this.p = p;
this.d = d;
}
public int compareTo(node n) //페이가 센 것 같다면 촉박한 순
{
if(p == n.p) return d - n.d;
else return n.p - p;
}
}
static long ans;
static boolean[] sche = new boolean[10001];
static int n;
static PriorityQueue<node> pq;
public static void main (String[] args) throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
n = Integer.parseInt(br.readLine());
pq = new PriorityQueue<>();
for(int i = 0 ; i < n ; i++)
{
st = new StringTokenizer(br.readLine());
int a = Integer.parseInt(st.nextToken());
int b = Integer.parseInt(st.nextToken());
pq.add(new node(a,b));
}
while(!pq.isEmpty())
{
node nod = pq.poll();
for(int i = nod.d ; i >= 1 ; i--) //리미트부터 1일까지 더듬어 가며 가능한 날 표시
{
if(!sche[i])
{
sche[i] = true;
ans += nod.p;
break;
}
}
}
System.out.println(ans);
}
}
'백준' 카테고리의 다른 글
백준(1132번) - 합 (Java) (그리디) (1) | 2023.07.12 |
---|---|
백준(11690번) - LCM(1, 2, ..., n)(Java) (수학) (0) | 2023.07.11 |
백준(2812번) - 크게 만들기(Java) (자료구조) (0) | 2023.07.09 |
백준(1644번) - 소수의 연속합(Java) (수학, 두 포인터) (0) | 2023.07.04 |
백준(2239번) - 스도쿠 (Java) (구현) (0) | 2023.07.02 |