import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine());
int n = Integer.parseInt(st.nextToken());
int[][] rock = new int[n][2];
int[] dp = new int[n + 1];
for (int i = 1; i < n; i++) {
st = new StringTokenizer(br.readLine());
rock[i][0] = Integer.parseInt(st.nextToken()); // 작은 점프
rock[i][1] = Integer.parseInt(st.nextToken()); // 큰 점프
}
int k = Integer.parseInt(br.readLine());
if (n >= 2) {
dp[2] = rock[1][0];
}
if (n >= 3) {
dp[3] = Math.min(rock[1][1], dp[2] + rock[2][0]);
}
int energy = Integer.MAX_VALUE;
if (n >= 4) {
for (int i = 4; i <= n; i++) { // 매우 큰 점프를 할 수 있는 위치
for (int j = 4; j <= n; j++) {
if (i == j) { // 큰 점프를 할 수 있는 돌의 위치
dp[j] = dp[j - 3] + k;
} else
dp[j] = Integer.MAX_VALUE;
dp[j] = Math.min(dp[j], Math.min(dp[j - 2] + rock[j - 2][1], dp[j - 1] + rock[j - 1][0]));
}
energy = Math.min(energy, dp[n]);
}
} else {
energy = dp[n];
}
System.out.println(energy);
}
}
매우 큰 점프를 전체에서 1번 사용할 수 없다는 조건을 제외하면 아주 쉽게 풀리는 문제이다.
dp[i] 를 dp[i] 돌까지 도달하는데 걸린 최소 에너지라고 하자.
매우 큰 점프를 제외한 dp점화식은 다음과 같다.
rock[i][0] => i번째 돌에서 작은 점프를 하기 위해 필요한 에너지
rock[i][1] => i번째 돌에서 큰 점프를 하기 위해 필요한 에너지
dp[i] = Math.min(dp[i-2] + rock[i-2][1], dp[i-1] + rock[i-1][0]);
그러나 여기서 매우 큰 점프를 추가한다면?
매우 큰 점프를 1번밖에 하지 못한다는 조건이 까다롭게 느껴졌다.
n<=20 이라 크지 않은 숫자이기 때문에,
큰 점프를 하여 도착하는 돌의 위치를 for문을 통해 지정하였고, 모든 케이스를 확인하였다. (i=4~n)
* 큰 점프을 하여 도달할 수 있는 돌은 4번째 돌부터 시작한다.
for (int i = 4; i <= n; i++) { // 매우 큰 점프를 할 수 있는 위치
for (int j = 4; j <= n; j++) { // dp[j] 구하기
if (i == j) { // 큰 점프를 할 수 있는 돌의 위치
dp[j] = dp[j - 3] + k;
} else
dp[j] = Integer.MAX_VALUE;
dp[j] = Math.min(dp[j], Math.min(dp[j - 2] + rock[j - 2][1], dp[j - 1] + rock[j - 1][0]));
}
energy = Math.min(energy, dp[n]);
}
만약 아주 큰 점프를 하여 j번째 돌에 도착하였다면? (i==j)
=> dp[j] = dp[j-3] + k 가 될 것이다.
따라서 작은 점프, 큰 점프, 아주 큰 점프를 하였을 때의 dp[j] 값을 비교하여 dp[j] 를 갱신해준다.
Math.min(dp[j-3]+k, Math.min(dp[j - 2] + rock[j - 2][1], dp[j - 1] + rock[j - 1][0]));
'알고리즘 > 동적프로그래밍(DP)' 카테고리의 다른 글
[백준] 2565번: 전깃줄 - java (0) | 2023.02.08 |
---|---|
[백준] 1106번: 호텔 - java (0) | 2023.02.08 |
[백준] 11660번: 구간 합 구하기 5 - java (1) | 2023.02.04 |
[백준] 1890번: 점프 - java (0) | 2023.02.02 |
[swea] 3282번: 0/1 Knapsack - 파이썬(python) (0) | 2022.11.12 |
댓글