在讲述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
本文用动态规划和改进的深度优先算法(记忆化搜索)两种办法
//(dp做法,找递归式ans[i][j] = max(ans[i+1][j],ans[i+1][j+1])+本身a[i][j])
//#include<iostream>
//#include<algorithm>
//#include<string>
//#include<string.h>
//#include<cstdio>
//#include<queue>
//#include<stack>
//#include<set>
//#include<map>
//#include<vector>
//using namespace std;
//int ans[105][105],a[105][105];
//int main(){
// int t = 0;
// cin >> t;
// while(t--){
// int n = 0;
// cin >> n;
// memset(ans,0,sizeof(ans));
// for(int i=1;i<=n;i++){
// for(int j=1;j<=i;j++){
// cin >> a[i][j];//输入各行数据
// }
// }
// for(int i=n;i>=1;i--){
// for(int j=1;j<=i;j++){
// ans[i][j] = max(ans[i+1][j],ans[i+1][j+1])+a[i][j];//从底层向上,计算各位置可得到的最大值再加上该位置本身的数字值
// }
// }
// cout << ans[1][1] << endl;//由于是自底向上,所以第一行的第一个数是所求的最大路径
// }
// return 0;
//}
(深搜改进做法(记忆化搜索))
//#include<iostream>
//#include<algorithm>
//#include<string>
//#include<string.h>
//#include<cstdio>
//#include<queue>
//#include<stack>
//#include<set>
//#include<map>
//#include<vector>
//using namespace std;
//int n;
//int ans[105][105],a[105][105];//a为存储点的数组,ans为所求结果数组
//int dfs(int i,int j){
// if(i == n){
// return ans[i][j] = a[i][j];//递归出口,i已经搜索到底部了
// }
// if(ans[i][j]>=0){//初始值为-1,ans数>=0,表示已经被访问过并且已得到相应的ans值(要不ans不会>=0),则直接返回当前数字,不再往下访问搜索
// return ans[i][j];//没有此if语句就是正常的dfs,加上这一步(记忆化搜索)可以降低时间复杂度2^n到n^2,避免重复访问和计算各点的ans
// }
// return ans[i][j] = max(dfs(i+1,j),dfs(i+1,j+1)) + a[i][j];
//}
//int main(){
// int t = 0;
// cin >> t;
// while(t--){
// cin >> n;
// memset(ans,-1,sizeof(ans));
// for(int i=1;i<=n;i++){
// for(int j=1;j<=i;j++){
// cin >> a[i][j];//输入各行数据
// }
// }
// cout << dfs(1,1) << endl;//从起点开始dfs
// }
// return 0;
//}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。