**例4:**数字三角形问题:给定一个有n行数字组成的数字三角形. 试设计一个算法, 计算出从三角形的顶至底的一条路径, 使该路径经过的数字和最大.(例题)
7 | ||||
---|---|---|---|---|
3 | 8 | |||
8 | 1 | 0 | ||
2 | 7 | 4 | 4 | |
4 | 5 | 2 | 6 | 5 |
一、确定状态:
终点:(n-1,i)前一个点(n - 2, i - 1)或(n - 2 ,i)
子问题:转化为到前一步有可能的两个点的和。设f[i] [j]为最大和。
二、确定转移方程:
f[i] [j] = max{f[i-1] [j-1] + a[i-1] [j-1],f[i-1] [j] + a[i-1] [j]}
三、确定初始条件和边界情况:
初始条件:f[0] [0] = a[0] [0];
边界情况:f[i] [0] = f[i-1] [0] + a[i-1] [0]
四、确定计算顺序:
从上至下
代码:
#include <iostream>
#include <cstring>
using namespace std;
int a[105][105];
int f[105][105];
void Init(){
memset(a, 0 ,sizeof(a));
memset(f, 0 ,sizeof(f));
}
int Max(int x, int y){
if(x >= y)
return x;
else
return y;
}
void F(int n){
f[0][0] = 0;
int i, j;
for(i = 0; i < n; i++)
{
for(j = 0; j <= i; j++)
{
if(!i && !j)
{
f[i][j] = a[i][j];
break;
}
if(i == j)
{
f[i][j] = f[i-1][j-1] + a[i][j];
}
else if(!j)
{
f[i][j] = f[i-1][j] + a[i][j];
}
else
{
f[i][j] = Max((f[i-1][j] + a[i][j]), (f[i-1][j-1] + a[i][j]));
}
}
}
}
int main(int argc, char** argv) {
Init();
int n;
cin>>n;
int i, j;
for(i = 0; i < n; i++)
{
for(j = 0; j <= i; j++)
cin>>a[i][j];
}
F(n);
int m = 0;
for(i = 0; i < n; i++)
{
if(f[n-1][i] > m)
m = f[n-1][i];
}
cout<<m<<endl;
return 0;
}
**总结:**这个题属于之前的最大(小)值类的问题,是学校oj上的一道作业题,思路比较简单,另外从下到上也可以,唯一困难的地方可能是在于题意的理解,从上一个点出发只能往右下或者正下方移动而不能往左下方移动,这点花了我很长时间,所幸得大佬指点(笑)