数塔
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 24591 Accepted Submission(s): 14793
Problem Description
在讲述DP算法的时候,一个经典的例子就是数塔问题,它是这样描述的:
有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
已经告诉你了,这是个DP的题目,你能AC吗?
有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
![](https://i-blog.csdnimg.cn/blog_migrate/79b65092734d6a263a9280f5b332c5b9.jpeg)
已经告诉你了,这是个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分析:这道题其实我们可以这样转化一下:d[i][j]为从塔的底端到a[i][j]的最长路径,这样,题目的解就转化成求d[1][1]了。首先,我们知道塔的最底层肯定是它本身了,所以d[i][j] = a[i][j](i == n时),那从倒数第二行起,每个数a[i][j]可以跟最后一行合并(现在原来的倒二成倒一行),再把原来的倒3行跟原来的倒2行合并(就跟消灭星星一样,只不过我们每次都消灭最后一行,把它与前一行合并),即状态的转移!根据题意,我们推出了这个状态转移式子:a[i][j] = max(a[i][j]+a[i+1][j],a[i][j]+a[i+1][j+1])(i!=n时)把以上两步综合起来就行了。#include <iostream> using namespace std; #define max(x,y) (x)>(y)?(x):(y); int a[150][150];//刚开始起存储矩阵原始值的作用,处理后状态转化了,储存从塔低端到a[i][j]的最长路径,也可以再用一个数组分别储存的 int main() { int c,n; cin >> c; if (!c) { return 0; } while (c--) { cin >> n;//填充矩阵 for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { if (i < j) { a[i][j] = 0; } else { cin >> a[i][j]; } } }//对矩阵做处理 for (int i = n; i >= 1; i--) { for (int j = n; j >= 1; j--) { if (i == n) { a[i][j] = a[i][j]; } else { a[i][j] += max(a[i+1][j],a[i+1][j+1]); } } } cout << a[1][1] << endl; } return 0; }//我的心得:这是刚开始自己做的一道dp题,之前都是在看各种博客啊,前面转的那篇 《Thinking In Algorithm》13.详解动态规划问题 是我觉得挺好的博客,看了几个例题,感觉都是用递归来表达最优解的。刚开始看这题,一直在想怎么递归出最优解。起初我是从塔顶开始的,我一行一行地递归,发现第i+1行跟第i行没有所谓的后面的状态由前面决定,下一行走的路线也可能跟前一行的路线不一样呀。后来才发现这个问题分的子问题那么细。。。。我自己瞎说的,仅供参考:dp问题(就我看到的例题):1.用递归的方法来推导出式子,得到最优子结构的解(最后再构造原问题解)2.跟分治一样,把问题分成很小的子问题,此时我们可以把每个问题看成一个状态,再由每个子问题之间的关系来进行状态转移。下面是专业人士总结的dp解题步骤:1. 利用Divide and Conquer把原問題遞迴地分成許多更小的問題。(recurrence) 甲、子問題與原問題的求解方式皆類似。(optimal sub-structure) 乙、子問題會一而再、再而三的出現。(overlapping sub-problems) 2. 確認每個問題需要哪些子問題來計算答案,並確認總共有哪些子問題。(state space) 3. 決定各個問題的計算先後次序。(computational sequence) 4. 安排好各個問題的答案,要存放在表格的哪個位置。(lookup table) 5. 實做程式,主要有兩種方式: 甲、Top-down, Recursive. 乙、Bottom-up, Iterative.