59 数字金字塔
作者: xxx时间限制: 1S章节: 二维数组
问题描述 :
考虑在下面被显示的数字金字塔(第n行有n列)。写一个程序来计算从最高点开始在底部任意处结束的路径经过数字的和的最大。每前进一步可以走到它的正下方或者右下方(往下一行、往右一列)的位置。
3 8 8 1 0 2 7 4 4 4 5 2 6 5 ``` 在上面的样例中,从7 到 3 到 8 到 7 到 5 的路径产生了最大和:30 输入说明 : 第一个行包含 R(1<= R<=1000) ,表示行的数目。后面每行为这个数字金字塔特定行包含的整数。所有的被供应的整数是非负的且不大于100。 输出说明 : 输出仅一行,包含那个可能得到的最大的和。 输入范例 : ```c 6 7 3 8 8 1 0 2 7 4 100 4 5 2 6 5 3 2 5 8 7 6 ``` 输出范例 : 129
代码:
/*
T59 数字金字塔
算法概述:
动态规划。设dp(i, j)为从(i,j)元素出发能达到的最大和
状态转移方程:dp(i, j)=data[i][j]+max{ dp(i + 1, j), dp(i + 1, j + 1) }
*/
/* 修改之后的代码(动态规划) */
#include<stdio.h>
#define MAX_SIZE 1005
int R;// 行数
int digitTower[MAX_SIZE][MAX_SIZE];// 数塔内的数据
int dp(int i, int j);
int main() {
int i = 0, j = 0;
scanf("%d", &R);
for (i = 1; i <= R; i++) {
for (j = 1; j <= i; j++)
scanf("%d", &digitTower[i][j]);
}
printf("%d\n", dp(1, 1));
return 0;
}
// 返回从(i, j)出发所能达到的最大和
int dp(int i, int j) {
int A = 0, B = 0;
if (i == R) {// 最后一行,递归出口
return digitTower[i][j];
}
A = dp(i + 1, j);// 向下走
B = dp(i + 1, j + 1);// 向右下走
return digitTower[i][j] + (A > B ? A : B);
}
害,之前做的时候不记得咋用动态规划了,卡了好久……
非递归版:
int R;// 行数
int digitTower[MAX_SIZE][MAX_SIZE];// 数塔内的数据
int result[MAX_SIZE][MAX_SIZE];// 存放结果
.
.
.
.
.
.
// 返回从(1, 1)出发所能达到的最大和(非递归版)
int dp() {
int i = 0, j = 0;
for (i = 1; i <= R; i++)// 最后一行的结果即为对应位置的数值
result[R][i] = digitTower[R][i];
for (i = R - 1; i >= 1; i--) {// 从下往上
for (j = 1; j <= i; j++) {// 从左往右
if (result[i + 1][j] > result[i + 1][j + 1]) {// 向下走
result[i][j] = digitTower[i][j] + result[i + 1][j];
}
else {
result[i][j] = digitTower[i][j] + result[i + 1][j + 1];// 向右下走
}
}
}
return result[1][1];
}