- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 (图1)
图1给出了一个数字三角形。从三角形的顶部到底部有很多条不同的路径。对于每条路径,把路径上面的数加起来可以得到一个和,你的任务就是找到最大的和。
注意:路径上的每一步只能从一个数走到下一层上和它最近的左边的那个数或者右边的那个数。 - 输入
- 输入的是一行是一个整数N (1 < N <= 100),给出三角形的行数。下面的N行给出数字三角形。数字三角形上的数的范围都在0和100之间。
- 输出
- 输出最大的和。
- 样例输入
-
5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5
样例输出
30
思路1:
(1,1)
(2,1)(2,2)
(3,1)(3,2)(3,3)
1、递推
(1,1) -> Max[(2,1),(2,2)] (1,1)往下找最大的数求和
(2,1) ->Max[(3,1),(3,2)]
(2,2) ->Max[(3,2),(3,3)]
(r,c)->Max [(r+1,c),(r+1,c+1)] (r,c)往下找最大的数求和
nSum1 nSum2 分别保存(r+1,c),(r+1,c+1)的数
2、判别大小,求和
若nSum1大,则 f(r,c)=nSum1+(r,c); 否则f(r,c)=nSum2+(r,c);
3、(1,1) 往下递归,直到第n层,即返回r=n时的(r,c)的值 。
#include<iostream> using namespace std; #define MAX 100 int arr[MAX+10][MAX-10]; int num; int MaxSum(int r,int j){ if(r==num) return arr[r][j]; int nSum1=MaxSum(r+1,j); int nSum2=MaxSum(r+1,j+1); if(nSum1>nSum2) { return nSum1+arr[r][j]; } return nSum2+arr[r][j]; } int main() { int x; while(cin>>num) { for(int i=1;i<=num;i++) for(int j=1;j<=i;j++) cin>>arr[i][j]; cout<<MaxSum(1,1)<<endl; } return 0; }
递归,OJ判定会超时。
不难总结规律,对于N行的三角形,总的计算次数是
2^0 + 2^1 + 2^2 + 2^3 + …… + 2^(N-1) = 2^N。
当N=100时,总的计算次数是一个很大的数字。
2^100=1,267,650,600,228,229,401,496,703,205,376 结果是31位的数。
思路2:
在思路1的基础上,将中间结果保存以避免重复计算。-》动态规划
#include<iostream> using namespace std; #include<memory.h> #define MAX 100 int arr[MAX+10][MAX-10]; int num; int aMaxSum[MAX+10][MAX+10]; int func(int r,int c){ if(r==num) return arr[r][c]; if(aMaxSum[r+1][c]==-1) //如果MaxSum(r+1,c)没计算过 aMaxSum[r+1][c]=func(r+1,c); if(aMaxSum[r+1][c+1]==-1) //如果MaxSum(r+1,c+1)没有计算过 aMaxSum[r+1][c+1]=func(r+1,c+1); if(aMaxSum[r+1][c]>aMaxSum[r+1][c+1]) return aMaxSum[r+1][c]+arr[r][c]; return aMaxSum[r+1][c+1] + arr[r][c]; } int main() { int x; // 将aMaxSum全部置-1,表示开始所有的MaxSum(r,c)都没计算过 memset(aMaxSum,-1,sizeof(aMaxSum)); while(cin>>num) { for(int i=1;i<=num;i++) for(int j=1;j<=i;j++) cin>>arr[i][j]; cout<<func(1,1)<<endl; } return 0; }思路3:
不用递归函数实现递归思想。从aMaxSum[N-1]这一行元素开始向上逐行递推得到aMaxSum[1][1],实现这一逆过程。
#include<iostream> using namespace std; #include<memory.h> #define MAX 100 int arr[MAX+10][MAX-10]; int num; int aMaxSum[MAX+10][MAX+10]; void prepare(){ for(int i=1;i<=num;i++) { aMaxSum[num][i]=arr[num][i]; } for(int i=num;i>1;i--) { for(int j=1;j<i;j++) { if(aMaxSum[i][j]>aMaxSum[i][j+1]) aMaxSum[i-1][j]=aMaxSum[i][j]+arr[i-1][j]; else aMaxSum[i-1][j]=aMaxSum[i][j+1]+arr[i-1][j]; } } } int main() { int x; while(cin>>num) { memset(aMaxSum,-1,sizeof(aMaxSum)); for(int i=1;i<=num;i++) for(int j=1;j<=i;j++) cin>>arr[i][j]; prepare(); cout<<aMaxSum[1][1]<<endl; } return 0; }