https://www.acmicpc.net/problem/12018
코드설명
완전탐색(BruteForce) + DFS(깊이우선탐색) + 동적계획법(Dynamic Programming, DP) 를 활용합니다.
문제를 완전탐색으로 접근했습니다. 다른 방법은 생각나지 않았습니다.
문제에서 N은 100이므로, 2^100 개의 탐색결과가 나와 시간초과가 발생할 수 있지만, 메모이제이션(Cache)를 적용하여 개선할 수 있습니다.
문제에서 4%에서 계속 틀렸었는데, 문제를 잘못읽었습니다.
처음에 만약 수강신청한 인원보다 과목 수강인원이 많다면, 마일리지를 0 원쓰고 들을 수 있다고 생각했습니다.
하지만, 문제에서 마일리지는 반드시 1~36 까지의 마일리지를 사용해야한다고 나옵니다.
//만약 선택한사람이 더 적다면,(수강인원이 더 많다면, 마일리지를 하나도 안쓰고 참여가능) if(L[level] > arr[level].length) return selectCache[level] = 1;
코드
정답코드입니다.
package Main; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.Collections; import java.util.StringTokenizer; public class Main { private static int N, T, K, M; private static int[][] arr; private static int[] L; private static int[][] cache; private static int[] selectCache; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); cache = new int[N+1][M+1]; selectCache = new int[N+1]; Arrays.fill(selectCache, -1); for(int i=0;i<=N;i++) { Arrays.fill(cache[i], -1); } arr = new int[N][]; L = new int[N]; for(int i=0;i<N;i++) { st = new StringTokenizer(br.readLine()); int P = Integer.parseInt(st.nextToken()); L[i] = Integer.parseInt(st.nextToken()); arr[i] = new int[P]; st = new StringTokenizer(br.readLine()); for(int j=0;j<P;j++) { arr[i][j] = Integer.parseInt(st.nextToken()); } Arrays.sort(arr[i]); } System.out.println(func(0, M)); } private static int func(int level, int mile) { if(level == N) { return 0; } if(cache[level][mile] != -1) return cache[level][mile]; int ret = 0; //선택안할경우 ret = Math.max(ret, func(level + 1, mile) + 0); //선택할경우 int cost = calculateCost(level); if(mile - cost >= 0) { // System.out.println("level:"+level+"cost:"+cost); ret = Math.max(ret, func(level + 1, mile-cost) + 1); } return cache[level][mile] = ret; } private static int calculateCost(int level) { if(selectCache[level] != -1) return selectCache[level]; //만약 선택한사람이 더 적다면,(수강인원이 더 많다면, 마일리지를 하나도 안쓰고 참여가능) if(L[level] > arr[level].length) return selectCache[level] = 1; int cnt = 0; int cost = 0; for(int i=arr[level].length - 1;i>=0;i--) { cnt += 1; if(L[level] == cnt) { cost = arr[level][i]; break; } } return selectCache[level] = cost; } }
처음에 시간초과 난 코드였다가 DP를 적용해서 시간초과를 해결했으나 4%에서 틀립니다.
package Main; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.Arrays; import java.util.Collections; import java.util.StringTokenizer; public class Main { private static int N, T, K, M; private static int[][] arr; private static int[] L; private static int[][] cache; public static void main(String[] args) throws IOException{ BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); N = Integer.parseInt(st.nextToken()); M = Integer.parseInt(st.nextToken()); cache = new int[N+1][M+1]; for(int i=0;i<=N;i++) { Arrays.fill(cache[i], -1); } arr = new int[N][]; L = new int[N]; for(int i=0;i<N;i++) { st = new StringTokenizer(br.readLine()); int P = Integer.parseInt(st.nextToken()); L[i] = Integer.parseInt(st.nextToken()); arr[i] = new int[P]; st = new StringTokenizer(br.readLine()); for(int j=0;j<P;j++) { arr[i][j] = Integer.parseInt(st.nextToken()); } Arrays.sort(arr[i]); } System.out.println(func(0, M)); } private static int func(int level, int mile) { if(level == N) { return 0; } if(cache[level][mile] != -1) return cache[level][mile]; int ret = 0; //선택안할경우 ret = Math.max(ret, func(level + 1, mile) + 0); //선택할경우 int cost = greedySelect(level); if(mile - cost >= 0) { ret = Math.max(ret, func(level + 1, mile-cost) + 1); } return cache[level][mile] = ret; } private static int greedySelect(int level) { //만약 선택한사람이 더 적다면, if(L[level] > arr[level].length) return 0; int cnt = 0; int cost = 0; for(int i=arr[level].length - 1;i>=0;i--) { cnt += 1; if(L[level] == cnt) { cost = arr[level][i]; break; } } return cost; } }
'알고리즘 > 백준' 카테고리의 다른 글
[백준] 13417 카드 문자열 - 그리디(Greedy, 탐욕법) JAVA (0) | 2024.08.02 |
---|---|
[백준] 12847 꿀 아르바이트 - 슬라이딩 윈도우(Sliding Window) + 자료형(Data Type) JAVA (0) | 2024.08.01 |
[백준] 10025 게으른 백곰 - 슬라이딩 윈도우(Sliding Window) JAVA (0) | 2024.07.29 |
[백준] 9659 돌 게임 5 - 동적계획법(DP, Dynamic Programming) + 게임이론(Game Theory) + 수학(Math) JAVA (0) | 2024.07.29 |
[백준] 9658 돌 게임 4 - 동적계획법(DP, Dynamic Programming) + 게임이론(Game Theory) JAVA (0) | 2024.07.29 |