본문 바로가기

숨막히는 알고말고/문제 풀이

[Baekjoon] 정수 삼각형

👀 문제 설명

문제

위 그림은 크기가 5인 정수 삼각형의 한 모습이다.

맨 위층 7부터 시작해서 아래에 있는 수 중 하나를 선택하여 아래층으로 내려올 때, 이제까지 선택된 수의 합이 최대가 되는 경로를 구하는 프로그램을 작성하라. 아래층에 있는 수는 현재 층에서 선택된 수의 대각선 왼쪽 또는 대각선 오른쪽에 있는 것 중에서만 선택할 수 있다.

삼각형의 크기는 1 이상 500 이하이다. 삼각형을 이루고 있는 각 수는 모두 정수이며, 범위는 0 이상 9999 이하이다.

 

입력

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

 

출력

첫째 줄에 합이 최대가 되는 경로에 있는 수의 합을 출력한다.

 

예제 입력 1

5

7

3 8

8 1 0

2 7 4 4

4 5 2 6 5

 

예제 출력 1

30

 

✍🏻풀이

DP를 사용해 각 위치까지의 최대값을 저장해두고, 마지막 줄의 값들 중 최댓값을 출력한다.

triangle[i][j]는 i층에 있는 j번째 숫자를 의미한다.

 

처음에는 큐를 사용해 위치를 넣어두고, 이동할 위치의 dp값을 구하려고 했으나 큐를 사용하니까 메모리 초과가 났다..

그래서 이중 for문을 사용해 각 위치의 DP값을 구해줬다.

현재 위치에서 갈 수 있는 방향은 왼쪽 아래, 오른쪽 아래이다. 이걸 바꿔서 생각해보면, 현재 위치로 올 수 있는 애들은 왼쪽 위, 오른쪽 위이므로 이걸 사용해 DP값을 구한다.

dp[ii][j] = max(dp[i - 1][j - 1] + triangle[i][j], dp[i - 1][j] + triangle[i][j]

라는 식을 사용하면 DP값을 구할 수 있고, 다 구한 다음, n층에 있는 DP값들 중 가장 큰 값을 출력해준다.

 

코드

#include <stdio.h>
#include <iostream>
#include <queue>

#define MAX 501

using namespace std;

int triangle[MAX][MAX]; // i층에 있는 j번째 숫자
int dp[MAX][MAX];
int dy[2] = { 0, 1 };

int main() {
    ios::sync_with_stdio(0);
    cin.tie(NULL); cout.tie(NULL);
    
    // input
    int n;
    cin >> n;
    
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            cin >> triangle[i][j];
        }
    }
    
    /**
     (i, j) 기준
     왼쪽 아래 : (i + 1, j)
     오른쪽 아래 : (i + 1, j + 1)
     
     (i, j) 기준
     왼쪽 위 : (i - 1, j - 1)
     오른쪽 위 : (i - 1, j)
     */
    int i = 1, j = 1;
    dp[i][j] = triangle[i][j];
    for (int i = 2; i <= n; i++) {
        for (int j = 1; j <= i; j++) {
            if (j - 1 > i - 1) { // 오른쪽 위가 범위를 벗어날 경우
                dp[i][j] = max(dp[i][j], dp[i - 1][j] + triangle[i][j]);
            }
            else if (i - 1 <= 0) { // 왼쪽 위가 범위를 벗어날 경우
                dp[i][j] = max(dp[i][j], dp[i - 1][j - 1] + triangle[i][j]);
            }
            else {
                dp[i][j] = max(dp[i - 1][j - 1] + triangle[i][j], dp[i - 1][j] + triangle[i][j]);
            }
        }
    }
    
    int ans = 0;
    for (int j = 1; j <= n; j++) {
        ans = max(ans, dp[n][j]);
    }
    
    cout << ans << "\n";
    
    
    return 0;
}

'숨막히는 알고말고 > 문제 풀이' 카테고리의 다른 글

[Baekjoon] 빵집  (0) 2021.03.01
[Baekjoon] 일곱 난쟁이  (0) 2021.02.28
[Baekjoon] 데스 나이트  (0) 2021.02.27
[Baekjoon] ⚾️  (0) 2021.02.25
[SWEA] 지그재그 숫자  (2) 2021.02.25