Baekjoon Online Judge - 9465
Review
포도주 시식, 계단 오르기랑 비슷한 문제이다. 다른 점은 두 줄이라는 점.
따라서 첫 번째 줄은 sticker[0][i], 두 번째 줄은 sticker[1][i] 이런 식으로 표현을 할 수 있다.
규칙은 기준점에서 대각선에 있는 스티커의 점수만 더할 수 있다.
하지만 문제는 두 칸, 세 칸 뒤의 대각선으로도 이동을 할 수 있다는 건데, 결론적으로는 두 칸까지의 이동만 비교하면 된다. 왜냐면 세 칸 뒤의 대각선은 이전 점수를 통해서 오는 게 더 높은 점수를 받을 수 있기 때문이다.
따라서 경우는 총 두 가지
- 기준점에서 한 칸 뒤의 대각선으로 이동하는 경우
- 기준점에서 두 칸 뒤의 대각선으로 이동하는 경우
각각의 경우를 점화식으로 나타내면 다음과 같다.
- dp[0][i] = Max(dp[1][i-1], dp[1][i-2]) + sticker[0][i]
- dp[1][i] = Max(dp[0][i-1], dp[0][i-2]) + sticker[1][i]
첫 번째 줄에서 시작한 경우, 두 번째 줄에서 시작한 경우를 각각 구한 다음, 둘 중 큰 수를 출력하면 된다.
여기서 sticker 배열은 스티커의 점수, dp 배열은 점수의 최대값을 저장한 배열이다.
문제 푸는 것보다 입력 받는 게 더 까다로웠다.
Code (JAVA)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| import java.io.*;
public class Main { public static void main(String args[]) throws IOException{ BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); int T = Integer.parseInt(bf.readLine()); while(T-- > 0) { int n = Integer.parseInt(bf.readLine()); int[][] dp = new int[2][100001]; int[][] sticker = new int[2][100001]; String[] str; for(int i = 0; i <= 1; i++) { str = bf.readLine().split(" "); for(int j = 1; j <= n; j++) { sticker[i][j] = Integer.parseInt(str[j-1]); } } dp[0][1] = sticker[0][1]; dp[1][1] = sticker[1][1]; for(int i = 2; i <= n; i++) { dp[0][i] = Math.max(dp[1][i-1], dp[1][i-2]) + sticker[0][i]; dp[1][i] = Math.max(dp[0][i-1], dp[0][i-2]) + sticker[1][i]; } System.out.println(Math.max(dp[0][n], dp[1][n])); } } }
|