IT/BOJ 문제정리

백준 1932번: 정수 삼각형

KimCookieYa 2021. 7. 10. 00:57

https://www.acmicpc.net/problem/1932

 

1932번: 정수 삼각형

첫째 줄에 삼각형의 크기 n(1 ≤ n ≤ 500)이 주어지고, 둘째 줄부터 n+1번째 줄까지 정수 삼각형이 주어진다.

www.acmicpc.net

 

 

0. 알고리즘 분류

 다이나믹 프로그래밍

 

 

1. 문제

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

 위 그림은 크기가 5인 정수 삼각형의 한 모습이다. 맨 위층 7부터 시작해서 아래에 있는 수 중 하나를 선택하여 아래층으로 내려올 때, 이제까지 선택된 수의 합이 최대가 되는 경로를 구하는 프로그램을 작성하라. 아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 대각선 오른쪽에 있는 것 중에서만 선택할 수 있다. 삼각형의 크기는 1 이상 500 이하이다. 삼각형을 이루고 있는 각 수는 모두 정수이며, 범위는 0 이상 9999 이하이다.

 

 

2. 풀이

 또 DP 문제다. 1149번의 "RGB 거리"와 매우 유사하다. 모양이 삼각형일 뿐. 우선 삼각형의 정수값을 받아들일 배열로 삼각형 모양으로 동적 배열을 사용했다. 그냥 2차원 배열을 써도 문제는 없지만, 될 것 같아서 그냥 했다.

 

 위에서부터 저장된 dp배열 두 값 중 최댓값을 dp배열에 저장하고 아래의 값을 더하면 된다. 하지만, 제일 왼쪽과 오른쪽변의 정수는 하나의 정수만을 받는다. 따라서 이를 염두에 두고 코딩한다.

 

 

3. 코드

#include <iostream>

using namespace std;

int max(int x, int y) {
	return (x > y) ? x : y;
}

int main(void) {
	int n;
	cin >> n;
	
	int** tri = new int*[n];
	int** dp = new int*[n];
	for (int i = 0; i < n; i++) {
		tri[i] = new int[i+1];
		dp[i] = new int[i+1];
		
		for (int j = 0; j <= i; j++) {
			cin >> tri[i][j];
		}
	}
	
	dp[0][0] = tri[0][0];
	for (int i = 1; i < n; i++) {
		for (int j = 0; j <= i; j++) {
			if (j == 0) {
				dp[i][j] = tri[i][j] + dp[i-1][j];
			}
			else if (j == i) {
				dp[i][j] = tri[i][j] + dp[i-1][j-1];
			}
			else {
				dp[i][j] = tri[i][j] + max(dp[i-1][j-1], dp[i-1][j]);
			}
		}
	}
	
	int ans = 0;
	for (int i = 0; i < n; i++) {
		if (ans < dp[n-1][i]) {
			ans = dp[n-1][i];
		}
	}
	cout << ans;
	
	for (int i = 0; i < n; i++) {
		delete tri[i];
		delete dp[i];
	}
	delete tri;
	delete dp;
	
	return 0;
}