1. 程式人生 > >Bailian2760 數字三角形【DP】

Bailian2760 數字三角形【DP】

2760:數字三角形
描述
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5

(圖1)

圖1給出了一個數字三角形。從三角形的頂部到底部有很多條不同的路徑。對於每條路徑,把路徑上面的數加起來可以得到一個和,你的任務就是找到最大的和。

注意:路徑上的每一步只能從一個數走到下一層上和它最近的左邊的那個數或者右邊的那個數。
輸入
輸入的是一行是一個整數N (1 < N <= 100),給出三角形的行數。下面的N行給出數字三角形。數字三角形上的數的範圍都在0和100之間。
輸出
輸出最大的和。
樣例輸入
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
樣例輸出
30
來源
翻譯自 IOI 1994 的試題

問題連結Bailian2760 數字三角形
問題描述:(略)
問題分析
    動態規劃問題,有2種解法。
    解法一:使用額外陣列,從底向上計算。需要注意陣列大小!要多一行和一列保證可靠。
    解法二:不使用額外陣列,自頂向下計算。
    這個題與參考連結是同一個題,只是輸入資料格式略有不同。
程式說明:(略)
參考連結HDU2084 數塔【DP】
題記:(略)

AC的C語言程式(解法一)如下:

/* Bailian2760 數字三角形 */

#include <stdio.h>
#include <string.h>

#define MAX(x, y) (((x) > (y)) ? (x) : (y))

#define N 100
int a[N + 1][N + 1], dp[N + 1][N + 1];

int main(void)
{
    int n, i, j;

    scanf("%d", &n);
    for(i = 0; i < n; i++)
        for(j = 0; j <= i; j++)
            scanf("%d", &a[i][j]);

    memset(dp, 0, sizeof(dp));
    for(i = n - 1; i >= 0; i--)
        for(j = 0; j <= i; j++)
            dp[i][j] = MAX(dp[i+1][j], dp[i+1][j+1]) + a[i][j];

    printf("%d\n", dp[0][0]);

    return 0;
}

AC的C語言程式(解法二)如下:

/* Bailian2760 數字三角形 */

#include <stdio.h>
#include <string.h>

#define MAX(x, y) (((x) > (y)) ? (x) : (y))

#define N 100
int grid[N][N];

int setmax(int n)
{
    int i, j;

    for(i=1; i<n; i++)
        for(j=0; j<=i; j++)
            if(j == 0)
                grid[i][j] += grid[i-1][j];
            else
                grid[i][j] = MAX(grid[i][j] + grid[i-1][j-1], grid[i][j] + grid[i-1][j]);

    int maxv = 0;
    for(i=n-1, j=0; j<n; j++)
        if(grid[i][j] > maxv)
            maxv = grid[i][j];

    return maxv;
}

int main()
{
    int n, i, j;

    scanf("%d", &n);

    memset(grid, 0, sizeof(grid));
    for(i = 0; i < n; i++) {
        for(j = 0; j <= i; j++)
            scanf("%d", &grid[i][j]);
    }

    printf("%d\n", setmax(n));

    return 0;
}