-
백준 1932번 숫자삼각형 [DP] :: 마이구미알고리즘 풀이/동적계획법 2017. 1. 3. 23:26반응형
이번 글은 백준 알고리즘 문제 1932번 "숫자삼각형" 을 다뤄본다.
이 문제의 풀이 방식은 DP(동적계획법)이다.
문제를 한번 보자.
7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
위 그림은 크기가 5인 숫자 삼각형의 한 모습이다.
맨 위층 7부터 시작해서 아래에 있는 수 중 하나를 선택하여 아래층으로 내려올 때, 이제까지 선택된 수의 합이 최대가 되는 경로를 구하는 프로그램을 작성하라. 아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 대각선 오른쪽에 있는 것 중에서만 선택할 수 있다.
맨 위층을 0층으로 가정하겠다.
1 층 : 7 -> 3 || 7 -> 8
2 층 : 7 -> 3 -> 8 || 7 -> 3 -> 1 || 7 -> 8 -> 1 || 7 -> 8 -> 0
..........................
위와 같이 선택하는 경우들이 있다.
먼저 dp 배열을 만들어보자.
문제에서 층 단위로 주어졌기에 dp배열은 2차원 배열로 만들면 된다.
결국 dp배열을 통해 꼭대기에서 각 층까지 선택한 수까지 합을 저장시키면 된다.
dp[i][j] = i번째 층에서 j인덱스의 수를 선택한 경우의 합
이제 dp 배열을 어떻게 저장시켜 나갈 지 위에서 말한 주의사항과 함께 생각해보자.
주의해야할 점은 문제에서 보다시피 아래층의 수를 선택하기 위해서는 대각선만 선택할 수 있다.
2층에서 3은 아래층의 8,1을 선택할 수 있고, 8은 아래층의 1,0을 선택할 수 있다.
여기서 3과 8은 아래층의 1을 중복으로 선택하게 된다.
이러한 규칙을 본다면 양 사이드에 있는 숫자가 아닌 수는 중복으로 선택된다는 점이다.
1. 현재 층에서 양 사이드에 있는 숫자를 선택한 경우
2. 현재 층에서 양 사이드의 숫자를 선택하지 않은 경우
현재층에서 윗층의 어떤 수에서 선택되었는지에 대한 경우들을 계산하면된다.
1번의 경우에서 왼쪽 사이드일 경우에는 윗층의 맨 왼쪽 인덱스(0) 의 값을 더해주면 된다.
1번의 경우에서 오른쪽 사이드일 경우에는 윗층의 맨 오른쪽 인덱스(i) 의 값을 더해주면 된다.
2번의 경우는 중복되는 경우이기 때문에 중복의 경우 중 가장 큰 값을 dp배열에 저장해야한다.
dp[i][j] = max( (현재층 + 윗층 왼쪽 대각선), (현재층 + 윗층 오른쪽 대각선) ) 이 될 수 있다.
for (int i = 1; i < n; i++) {
for (int j = 0; j <= i; j++) {
if (j == 0) {
dp[i][j] += dp[i-1][j];
} else if (j == i) {
dp[i][j] += dp[i-1][j-1];
} else {
dp[i][j] = max(dp[i][j] + dp[i-1][j-1], dp[i][j] + dp[i-1][j]);
}
}
}
문제를 먼저 완벽히 이해하고 본다면 쉽게 이해가 갈 것이다.
GitHub에 전체 소스가 있으니 확인하길 바란다.
이만 안녕.
Github URL 문제 소스
https://github.com/hotehrud/acmicpc/blob/master/dp/1932.java
백준 1932번 숫자삼각형
https://www.acmicpc.net/problem/1932
반응형'알고리즘 풀이 > 동적계획법' 카테고리의 다른 글
백준 3745번 오름세 [LIS] :: 마이구미 (0) 2017.02.17 백준 2579번 계단 오르기 [DP] :: 마이구미 (4) 2017.01.16 백준 2156번 포도주 시식 [DP] :: 마이구미 (5) 2017.01.16 백준 1912번 연속합 [DP] :: 마이구미 (4) 2017.01.15 백준 2688번 줄어들지 않아 [DP] :: 마이구미 (0) 2017.01.02