题目描述
有形如图所示的数塔,从顶部出发,在每一结点可以选择向左走或是向右走,一起走到底层,要求找出一条路径,使路径上的值最大。
这道题如果用枚举法,在数塔层数稍大的情况下(如40),则需要列举出的路径条数将是一个非常庞大的数目。如果用贪心法又往往得不到最优解。在用动态规划考虑数塔问题时可以自顶向下的分析,自底向上的计算。从顶点出发时到底向左走还是向右走应取决于是从左走能取到最大值还是从右走能取到最大值,只要左右两道路径上的最大值求出来了才能作出决策。同样的道理下一层的走向又要取决于再下一层上的最大值是否已经求出才能决策。这样一层一层推下去,直到倒数第二层时就非常明了。所以实际求解时,可从底层开始,层层递进,最后得到最大值。
一般说来,很多最优化问题都有着对应的计数问题;反过来,很多计数问题也有着对应的最优化问题。因此,我们在遇到这两类问题时,不妨多联系、多发展,举一反三,从比较中更深入地理解动态规划的思想。
其实递推和动态规划这两种方法的思想本来就很相似,也不必说是谁借用了谁的思想。关键在于我们要掌握这种思想,这样我们无论在用动态规划法解最优化问题,或是在用递推法解判定型、计数问题时,都能得心应手、游刃有余了。
输入
第一行输入一个整数n (不超过40)
然后是n行,每行代表数塔上对应的数值
输出
输出从顶上到底层的最大值,格式见样例
样例输入 Copy
3 3 1 2 1 2 3
样例输出 Copy
max=8
#include<iostream>
#include<cmath>
using namespace std;
const int MAXN = 1000;
int f[MAXN][MAXN];
int max(int a, int b)
{
if (a > b)
{
return a;
}
else
{
return b;
}
}
int main()
{
int n;
cin >> n;
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= i; j++)
{
cin >> f[i][j];
}
}
for (int i = n-1; i >= 1; i--)
{
for (int j = 1; j <= i; j++)
{
f[i][j] += max(f[i+1][j],f[i+1][j+1]);
}
}
cout << "max="<<f[1][1] << endl;
return 0;
}