- 教材习题6第1题。
有数字三角形如下:
找出从第一层到最后一层的一条路,使得所经过的权值之和最小或者最大。
#include<iostream>
using namespace std;
const int N=50;
int main()
{
cout << "Please input N(lines): " ;
//数塔的层数
int n;
cin >> n;
int d[N+1][N+1][3]; //[1]用来存数,[2]参与运算,[3]表示向左(0),还是向右(1)
//输入数塔
for(int i = 1; i <= n; ++i)
{
cout << "Please input line"<< i<<": ";
for(int j = 1; j <= i; ++j) //第i行有i个数
{
cin >> d[i][j][1];
d[i][j][2] = d[i][j][1];
d[i][j][3] = 0;
}
}
cout << endl;
for( i = n-1; i >= 1; --i) //从倒数第二行开始
{
for(int j=1; j <= i; j++)
{
if (d[i+1][j][2] > d[i+1][j+1][2])
{
d[i][j][2] += d[i+1][j][2];
d[i][j][3] = 0;
}
else
{
d[i][j][2] += d[i+1][j+1][2];
d[i][j][3] = 1;
}
}
}
//输出数塔
for( i = 1; i <= n; ++i)
{
for(int j = 1; j <= i; ++j)
{
cout << d[i][j][1] << " ";
}
cout << endl;
}
cout << "Max:"<<d[1][1][2] << endl;
//输出路径
int j;
for(i = 1, j = 1; i<= n; ++i)
{
cout << "[" << i << "," << j << "]" << " -> ";
j += d[i][j][3];
}
cout << "结束"<<endl;
return 0;
}
结果如下:
提示:
以所经过的权值之和最大值为例进行说明。
行进的过程中,每次只有两种选择:向左或向右。一个有n层的数字三角形的完整路径有2n条,所以当n比较大的时候,搜索全部路径,从中找出最大值,效率较低。
采用动态规划方法实现。
用d(i,j)表示从位置(i,j)出发时得到的最大值(包括位置(i,j)本身),可以写出最大值的递归方程:
由于递归方程中包含了重复子问题,直接采用递归方程求解, 效率较低。采用动态规划的方法,用一张二维表记录中间过程的值,可以把时间效率提高到n2。