http://poj.org/problem?id=3176
题意:输入n层数字三角形,求从第一层到最后一层最大权值和。
其实用递归很简单的解决,但是数据范围是350层,递归确实可以解决,但是会超时。
很容易看出来,maxn(i,j)是第i层第j数字到底层的最大权值和,所以要求maxn(i,j)有两种选择a(i,j)+MAX(maxn(i+1,j),maxn(i+1,j+1));
很明显这个超时代码对于一些值进行了重复计算。
#include<iostream>
using namespace std;
int n,a[355][355];
int maxn(int l,int r)
{
if(l == n)
return a[l][r];
int s1 = maxn(l+1,r);
int s2 = maxn(l+1,r+1);
if(s1 > s2)
return s1+a[l][r];
return s2+a[l][r];
}
int main()
{
cin>>n;
for(int i = 1;i <= n; i++)
for(int j = 1;j <= i; j++){
cin>>a[i][j];
}
cout<<maxn(1,1)<<endl;
return 0;
}
当然可以数组表示,这样的话可以记录它是否算过。
#include<iostream>
#include<cstring>
using namespace std;
int n,a[355][355];
int b[355][355];
int maxn(int l,int r)
{
if(l == n)
return a[l][r];
if(b[l+1][r] == -1)
b[l+1][r] = maxn(l+1,r);
if(b[l+1][r+1] == -1)
b[l+1][r+1] = maxn(l+1,r+1);
if(b[l+1][r] > b[l+1][r+1])
return b[l+1][r] + a[l][r];
return b[l+1][r+1]+a[l][r];
}
int main()
{
memset(b,-1,sizeof(b));
cin>>n;
for(int i = 1;i <= n; i++)
for(int j = 1;j <= i; j++){
cin>>a[i][j];
}
cout<<maxn(1,1)<<endl;
return 0;
}
这个 a(i,j)+MAX(maxn(i+1,j),maxn(i+1,j+1))式子可以说明了其中的规律。因此甚至可以不用递归。
#include<iostream>
using namespace std;
int n,a[355][355],b[355][355];
int main()
{
cin>>n;
for(int i = 1;i <= n; i++)
for(int j = 1;j <= i; j++)
cin>>a[i][j];
for(int i = 1;i <= n; i++)
b[n][i] = a[n][i];
for(int i = n;i > 1; i--){
for(int j = 1;j < i; j++)
if(b[i][j] > b[i][j+1])
b[i-1][j] = b[i][j] + a[i-1][j];
else b[i-1][j] = b[i][j+1] + a[i-1][j];
}
cout<<b[1][1]<<endl;
return 0;
}