• 백준 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



    반응형

    댓글

Designed by Tistory.