1.题目
数字三角形问题
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
给定一个由n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形的顶至底的一条路径,使该路径经过的数字总和最大。
对于给定的由n行数字组成的数字三角形,计算从三角形的顶至底的路径经过的数字和的最大值。
Input
输入数据的第1行是数字三角形的行数n,1≤n≤100。接下来n行是数字三角形各行中的数字。所有数字在0..99之间。
Output
输出数据只有一个整数,表示计算出的最大值。
Sample Input
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
Sample Output
30
2.正确代码
#include <iostream>
using namespace std;
int main()
{
int n;
int arr[101][101],i,j;
while(cin >> n)
{
for(i=1;i<=n;i++)
for(j=1;j<=i;j++)
cin >> arr[i][j];
for(i=n-1;i>=1;i--)
for(j=1;j<=i;j++)
arr[i][j]+=arr[i+1][j]>arr[i+1][j+1]?arr[i+1][j]:arr[i+1][j+1];
cout << arr[1][1] << endl;
}
}
3.代码解读:
1.这个题目代码不是问题,单看这个题的思路也不是问题,但我们如何来看待这一类问题呢?
2.按常理,是从前往后把每种可能写起来,但为什么不能从前往后推呢?我们也可以把结果存起来啊?
3.我们现在就来思考这个问题,为什么不能从前往后推,是什么原因导致的?
4.因为,从前往后,我们所要面临的选择越来越多,如1->2,本来由一个,这样会推导出两种可能,这两种都有可能是最优解,这样随着进行下去,我们所面临的选择越来越多,最优解的潜在可能也越来越多,这算法自然很劣势。
5.但如果你从后往前推,那么可能性是越来越小的,即你最优解可以选择的范围越来越小,并且最后推到时必然是最优解,可以,你又会问,你如何能证明这个是最优解?这个题目性质本身就是纯数值的积累,不存在路径弯道之类的,故,每个值最大,那么结果一定最大。
6.那么以后什么问题都用这种不是都可行吗?当然不行,不仅每次选择的条件,还有一个重要的,这里“最后”的数值即确定了,即结尾一定确定,数据都出来了,不存在其他的未知数据。
7.所以,当以后数据都已给出,注意,从大可能往小可能方向查找,而非倒过来,很简单。