有如下所示的数塔,要求从顶层走到底层,若每一步只能走到相邻的结点,则经过的结点的数字之和最大是多少?
输入数据首先包括一个整数C,表示测试实例的个数,每个测试实例的第一行是一个整数N(1 <= N <= 100),表示数塔的高度,接下来用N行数字表示数塔,其中第i行有个i个整数,且所有的整数均在区间[0,99]内。
从顶点出发时到底向左走还是向右走应取决于是从左走能取到最大值还是从右走能取到最大值,只要左右两道路径上的最大值求出来了才能作出决策。
同样,下一层的走向又要取决于再下一层上的最大值是否已经求出才能决策。这样一层一层推下去,直到倒数第二层时就非常明了。
如数字2,只要选择它下面较大值的结点19前进就可以了。所以实际求解时,可从底层开始,层层递进,最后得到最大值。
结论:自顶向下的分析,自底向上的计算。
1
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
DP思路: 自底向上,每一层每一个数都有一个sum,最底层的sum就是数字本身,倒数第二层每个数选择sum比较大的加上自身作为sum,这样每个数字都有一个从它开始到最底层最大的sum。。。。。。。直到最高层,一选就可以得到最大和了。
code:
#include <iostream>
using namespace std;
int main()
{
int N;
cin>>N;
int** tower = new int*[N]; //二维数组的动态创建及初始化!!
for(int i=0;i<N;i++)
{
tower[i] = new int[i+1];
for(int j=0;j<i+1;j++)
{
cin>>tower[i][j];
}
}
int** sum = new int*[N];
for(int i=0;i<N;i++)
{
sum[i] = new int[i+1];
for(int j=0;j<=i;j++)
sum[i][j] = 0;
}
for(int i=0;i<N;i++)
sum[N-1][i] = tower[N-1][i];
for(int i=N-2;i>=0;i--)
{
for(int j=0;j<=i;j++)
{
sum[i][j] += (sum[i+1][j]>=sum[i+1][j+1])?(sum[i+1][j]):(sum[i+1][j+1]);
sum[i][j] += tower[i][j];
}
}
cout<<sum[0][0]<<endl;
delete []tower;
delete []sum;
return 0;
}