Problem Description
在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:
有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
已经告诉你了,这是个DP的题目,你能AC吗?
Input
输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。
Output
对于每个测试实例,输出可能得到的最大和,每个实例的输出占一行。
Sample Input
1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
Sample Output
30
Source
2006/1/15 ACM程序设计期末考试
Recommend
lcy | We have carefully selected several similar problems for you: 1176 1003 1087 1159 1069
以下是他人的题解,比较详细就用了:来自http://blog.csdn.net/ZhengZhiRen/article/details/4129081
有形如图所示的数塔,从顶部出发,在每一结点可以选择向左走或是向右走,
一直走到底层,要求找出一条路径,使路径上的值最大。
这道题如果用枚举法,在数塔层数稍大的情况下(如40),则需要列举出的路径条数将是一个非常庞大的数目。
如果用贪心法又往往得不到最优解。
在用动态规划考虑数塔问题时可以自顶向下的分析,自底向上的计算。
从顶点出发时到底向左走还是向右走应取决于是从左走能取到最大值还是从右走能取到最大值,
只要左右两道路径上的最大值求出来了才能作出决策。
同样的道理下一层的走向又要取决于再下一层上的最大值是否已经求出才能决策。
这样一层一层推下去,直到倒数第二层时就非常明了。
如数字2,只要选择它下面较大值的结点19前进就可以了。
所以实际求解时,可从底层开始,层层递进,最后得到最大值。
总结:此题是最为基础的动态规划题目,阶段、状态的划分一目了然。
而决策的记录,充分体现了动态规划即“记忆化搜索”的本质。
小结:总体是自下而上,关键(状态转移方程)是:a[i][j]+=max(a[i+1][j],a[i+1][j+1]);本人代码如下:
#include<stdio.h>
#include<math.h>
int max(int a,int b)
{
if(a>b)
return a;
else return b;
}
int main()
{
int c,a[110][110],n,i,j,k;
scanf("%d",&c);
for(k=0;k<c;k++)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
scanf("%d",&a[i][j]);
for(i=n-1;i>0;i--)
for(j=1;j<=i;j++)
a[i][j]+=max(a[i+1][j],a[i+1][j+1]);
printf("%d\n",a[1][1]);
}
return 0;
}