728x90
https://www.acmicpc.net/problem/1932
문제
위 그림은 크기가 5인 정수 삼각형의 한 모습이다.
맨 위층 7부터 시작해서 아래에 있는 수 중 하나를 선택하여 아래층으로 내려올 때, 이제까지 선택된 수의 합이 최대가 되는 경로를 구하는 프로그램을 작성하라. 아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 대각선 오른쪽에 있는 것 중에서만 선택할 수 있다.
삼각형의 크기는 1 이상 500 이하이다. 삼각형을 이루고 있는 각 수는 모두 정수이며, 범위는 0 이상 9999 이하이다.
입력
첫째 줄에 삼각형의 크기 n(1 ≤ n ≤ 500)이 주어지고, 둘째 줄부터 n+1번째 줄까지 정수 삼각형이 주어진다.
출력
첫째 줄에 합이 최대가 되는 경로에 있는 수의 합을 출력한다.
코드 1 (반복문)
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <vector>
#include <stack>
using namespace std;
int N;
int num[501][501];
int cache[501][501];
int main() {
cin >> N;
cin >> num[0][0];
cache[0][0] = num[0][0];
for(int i=1; i<N; ++i){
for(int j=0; j<i+1; ++j){
cin >> num[i][j];
if(j != 0){
cache[i][j] = max(cache[i-1][j], cache[i-1][j-1]) + num[i][j];
}
else{
cache[i][0] = num[i][0] + cache[i-1][0];
}
}
}
int maxx = -1;
for(int i=0; i<N; ++i){
if(maxx < cache[N-1][i]){
maxx = cache[N-1][i];
}
}
cout << maxx;
return 0;
}
dp와 반복문을 사용해서 푼 풀이이다.
이 문제의 전형적인 답안으로 위쪽 부분에서(삼각형에서 층수가 높은쪽) cache의 최대값을 찾아나가며 해결하는 풀이이다.
반복문을 사용해서 dp를 풀면 좀 더 간결하고 최적화(슬라이딩 윈도 기법) 방법도 사용할 수 있지만 직관적이지 못하다.
따라서 재귀를 사용해서 다시 풀어주었다.
코드 2 (재귀)
#include <algorithm>
#include <cstring>
#include <iostream>
#include <map>
#include <set>
#include <stack>
#include <vector>
using namespace std;
int n;
int cache[501][501];
int num[501][501];
int triangle(int y, int x){
if(y == n-1){
return num[y][x];
}
int& ret = cache[y][x];
if(ret != -1){
return cache[y][x];
}
return ret = max(triangle(y+1,x), triangle(y+1, x+1)) + num[y][x];
}
int main() {
cin >> n;
memset(cache, -1, sizeof(cache));
for(int i=0; i<n; ++i){
for(int j=0; j<i+1; ++j){
cin >> num[i][j];
}
}
cout << triangle(0, 0);
return 0;
}
반복문과 달리 재귀로 풀때는 삼각형 아래쪽 방향을 향해 순서대로 최대값을 찾아가며 풀어줄 수 있다.
재귀로 풀면 좀 더 직관적일 뿐만 아니라 부분 문제간의 의존 관계를 고민할 필요가 없어진다.
728x90
반응형
'PS > DP' 카테고리의 다른 글
[10844] 쉬운 계단 수 (0) | 2023.04.14 |
---|---|
[1463] 1로 만들기 (0) | 2023.04.13 |
[1149] RGB거리 (0) | 2023.04.11 |
[1904] 01타일 (0) | 2023.04.01 |
[9184] 신나는 함수 실행 (0) | 2023.03.30 |