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 |