PS/DP

[1932] 정수 삼각형

프레딕 2023. 4. 13. 22:20
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
반응형