백준 13302 - 리조트
Updated:
Java
13302 번 - 리조트
문제
접근 방법
Bottom-up DP를 통해 해결하였다.
문제를 푼 후, 다른 분들의 풀이를 보니 조금 다른 점이 있었다.
내가 사용한 dp[a][b]
는
a일째에 b개의 쿠폰을 가졌을 때까지 사용한 총 금액의 최소값
따라서, N 일째가 넘었을 때 사용한 총 금액을 구하고, 그 최소 금액이 정답이 된다.
코드
import java.util.*;
import java.io.*;
public class Main {
static final int MAX_INT = 987654321, ONE_D = 10000, THREE_D = 25000, FIVE_D = 37000;
static int n, m, result = MAX_INT;
static int[][] dp;
static boolean[] plan;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer stk = new StringTokenizer(br.readLine());
n = stoi(stk.nextToken());
m = stoi(stk.nextToken());
plan = new boolean[n + 1];
dp = new int[n + 1][100];
for(int i = 0; i <= n; i++) {
Arrays.fill(dp[i], MAX_INT);
}
Arrays.fill(plan, true);
// m이 0이면 다음 입력을 받지 않는다.
if(m != 0)
stk = new StringTokenizer(br.readLine());
int curD;
for(int i = 0; i < m; i++) {
curD = stoi(stk.nextToken());
plan[curD] = false;
}
DFS(1,0,0);
System.out.println(result);
br.close();
}
static void DFS(int day, int cupon, int sum) {
// 총 금액의 최소를 구한다.
if(day > n) {
result = Math.min(sum, result);
return;
}
// day 번째 날 cupon 개의 쿠폰을 가지고 있을 때까지 사용한 최소 금액을 구한다.
if(dp[day][cupon] > sum) {
dp[day][cupon] = sum;
}
else {
return;
}
//휴일 일 때
if(!plan[day]) {
DFS(day + 1, cupon, sum);
}
// 쿠폰이 3장 이상일 때
if(cupon >= 3) {
DFS(day + 1, cupon - 3, sum);
}
DFS(day + 1, cupon, sum + ONE_D);
DFS(day + 3, cupon + 1, sum + THREE_D);
DFS(day + 5, cupon + 2, sum + FIVE_D);
}
static int stoi(String str) {
return Integer.parseInt(str);
}
}
Top - down 방식으로 해결하면
dp[a][b]
를 a번째 날, b개의 쿠폰을 가지고 있을 때, 리조트에 들어가는데 들어가는 최소비용 이라고 생각하여 다음과 같이 풀수있다.
static int DFS(int day, int cupon) {
if(day > n) {
return 0;
}
// 이미 한번 방문했으면 추가로 방문하지 않는다.
if(dp[day][cupon] != MAX_INT) {
return dp[day][cupon];
}
// 만약 방문하지 않는 날일 때
if(!plan[day]) {
return dp[day][cupon] = DFS(day + 1, cupon);
}
dp[day][cupon] = Math.min(dp[day][cupon], DFS(day + 1, cupon) + ONE_D);
dp[day][cupon] = Math.min(dp[day][cupon], DFS(day + 3, cupon + 1) + THREE_D);
dp[day][cupon] = Math.min(dp[day][cupon], DFS(day + 5, cupon + 2) + FIVE_D);
if(cupon >= 3) {
dp[day][cupon] = Math.min(dp[day][cupon], DFS(day + 1, cupon - 3));
}
return dp[day][cupon];
}
위 두 코드의 차이는, dp[a][b]
에서 a 일자가 흘러가며 돈을 쌓아가는 방식인가(Bottom-Up),
아님 dp[1][0]
으로 모이는 것인가(Top-down)의 차이이다.
총평
후기
해당 블로그가 많이 도움되었다.
https://yabmoons.tistory.com/405