一、题目

数塔问题 :要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
二、解题思路
动态规划解题思路可详见另一篇文章。数塔中元素用二维数组a[][]表示
①定义状态
由题意可设dp[i][j]为第i层的第j个顶点到底层经过的最大数字和。
②定义状态转移方程
大家知道动态规划满足无后向性,即:每个阶段的决策仅受之前决策的影响,但是不影响之后各阶段的决策。所以我们可以从后往前推出状态转移方程(逆向思维),dp[0][0]等于第1层第1个数字到底层经过的最大数字和,它等于dp[1][0] + a[0][0]或dp[1][1] + a[0][0]中的最大的数值。我们可以公式化,得到如下状态转换方程:
dp[i][j] = max( dp[i+1][j] + dp[i+1][j+1] ) + a[i][j]
③确定边界
由状态定义我们可以得出当数字在最底层时,它到最底层就是数字本身,即可得出dp[i][j] = a[i][j] (0≤i,j≤N)
三、代码编写
-
#include <stdio.h>
-
#include <stdlib.h>
-
-
#define N 5
-
#define max(a,b) ((a>b)?a:b)
-
-
int main()
-
{
-
//保存数塔元素
-
int a[N][N] = { {
9,
0,
0,
0,
0},
-
{
12,
15,
0,
0,
0},
-
{
10,
6,
8,
0,
0},
-
{
2,
18,
9,
5,
0},
-
{
19,
7,
10,
4,
16}};
-
//dp[i][j]为第i层的第j个顶点到底层经过的最大数字和
-
int dp[N][N] = {
0};
-
//确定边界数值
-
int i,j;
-
for(i=
0;i < N;i++){
-
dp[N
-1][i] = a[N
-1][i];
-
}
-
//核心算法
-
for(i=N
-2;i >=
0;i--){
-
for(j=
0; j < i+
1 ;j++){
-
dp[i][j] = max(dp[i+
1][j],dp[i+
1][j+
1]) + a[i][j];
-
}
-
}
-
-
printf(
"DP矩阵为:\n");
-
for(i=
0;i < N;i++){
-
for(j=
0; j <= i ;j++){
-
printf(
"%d ",dp[i][j]);
-
}
-
printf(
"\n");
-
}
-
printf(
"顶层到底层的经过的最大数字和为:%d",dp[
0][
0]);
-
return
0;
-
}
四、运行结果

五、总结
动态规划需要满足无后向性,可用逆向思维推出状态转化方程,动态规划解题方法可详见另一篇文章。

8841

被折叠的 条评论
为什么被折叠?



