首先说明:以下数行注视来自这为兄台的博客,他写的详细,我就直接借用了:(代码是自己的)
http://blog.csdn.net/ZhengZhiRen/article/details/4129081
- /*
- 数塔问题:
- 9
- 12 15
- 10 6 8
- 2 18 9 5
- 19 7 10 4 16
- 有形如图所示的数塔,从顶部出发,在每一结点可以选择向左走或是向右走,
- 一直走到底层,要求找出一条路径,使路径上的值最大。
- 这道题如果用枚举法,在数塔层数稍大的情况下(如40),则需要列举出的路径条数将是一个非常庞大的数目。
- 如果用贪心法又往往得不到最优解。
- 在用动态规划考虑数塔问题时可以自顶向下的分析,自底向上的计算。
- 从顶点出发时到底向左走还是向右走应取决于是从左走能取到最大值还是从右走能取到最大值,
- 只要左右两道路径上的最大值求出来了才能作出决策。
- 同样的道理下一层的走向又要取决于再下一层上的最大值是否已经求出才能决策。
- 这样一层一层推下去,直到倒数第二层时就非常明了。
- 如数字2,只要选择它下面较大值的结点19前进就可以了。
- 所以实际求解时,可从底层开始,层层递进,最后得到最大值。
- 总结:此题是最为基础的动态规划题目,阶段、状态的划分一目了然。
- 而决策的记录,充分体现了动态规划即“记忆化搜索”的本质。
- */
#include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> #define MAX_ARRAY_SIZE 20 int data[MAX_ARRAY_SIZE][MAX_ARRAY_SIZE];//存放最初的数据 int cost[MAX_ARRAY_SIZE][MAX_ARRAY_SIZE];//存放各个子问题的最优解 int mark[MAX_ARRAY_SIZE][MAX_ARRAY_SIZE];//存放输出最优解方案标志 int main(int argc,char *argv[]) { //初始化data int n; scanf("%d",&n); int i,j; for(i=0;i<n;i++){ for(j=0;j<=i;j++){ scanf("%d",&data[i][j]); } } //dp初始化 for(i=0;i<n;i++){ cost[n-1][i]=data[n-1][i]; } //dp运行 for(i=n-2;i>=0;i--){ for(j=0;j<=i;j++){ if(cost[i+1][j]>cost[i+1][j+1]){ cost[i][j]=data[i][j]+cost[i+1][j]; mark[i][j]=0; }else{ cost[i][j]=data[i][j]+cost[i+1][j+1]; mark[i][j]=1; } } } printf("max: %d\n",cost[0][0]); for(i=0,j=0;i<n;i++){ printf("line:%d,value: %d\n",i+1,data[i][j]); if(mark[i][j]==1) j=j+1; } return 0; }