数字三角形问题(动态规划)
Description
下图给出了一个数字三角形,请编写一个程序,计算从顶至底的某处的一条路径,使该路径所经过的数字和最大
Input
有很多个测试案例,对于每一个测试案例, 通过键盘逐行输入,第1行是输入整数(如果该整数是0,就表示结束,不需要再处理),表示三角形行数n,然后是n行数
Output
输出最大值
Example Input
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
Example Output
30
标准的动态规划问题,设一个dp数组,代表当前坐标下的最大路径,arr数组用来存储数字。我们从最后一层倒过来考虑,转换思路,从下向上求出答案状态转移方程式:dp(i)(j)= max(dp(i + 1)(j), a(i + 1)(j + 1))同时利用模拟队列的方法输出路径 。用一个队列,tail表示每一个输入数字的标号,(1—(1+n)*n/2),同时记录每一个数字的父亲点
#include <iostream>
#include <algorithm>
using namespace std;
int arr[21][21];
int dp[21][21];
struct que {
int x;
int y;//记录编号为tail的坐标
int f;//记录父亲点
}q[410];
void print(int l)
{
cout <<'(' << q[l].x <<','<< ' ' << q[l].y <<')' << endl;
//注意cout的位置,放在此处先行打印,才可以将终点打印出来
if (q[l].f != 0)
{
print(q[l].f);
}
}
int main(void)
{
int n,i,j;
int tail;
cin >> n;
tail = 1;
for (i = 1; i <= n; i++)
{
for (j = 1; j <= i; j++)
{
cin >> arr[i][j];
}
}//输入数字
for (j = 1; j <= n; j++)
{
dp[n][j] = arr[n][j];//初始化
q[tail].x = n;
q[tail].y = j;
q[tail].f = 0;//设最后一行初始值为0
tail++;
}
for (i = n - 1 ; i >= 1; i--)
{//从倒数第二行开始遍历
for (j = 1; j <= i; j++)
{
if (dp[i + 1][j] > dp[i + 1][j + 1])
{
dp[i][j] = dp[i+1][j] + arr[i][j];
q[tail].x = i ;
q[tail].y = j;
q[tail].f = tail-i-1;//记录当前点(tail)的父亲点的编号tail-i-1,画出三角形观察规律可得当前编号与父亲点编号为i+1
}
else
{
dp[i][j] = dp[i + 1][j + 1] + arr[i][j];
q[tail].x = i ;
q[tail].y = j ;
q[tail].f = tail-i;
}
tail++;
}
}
tail--;
cout <<"最大的步数为"<< dp[1][1] << endl;
cout << "路径为" << endl;
print(tail);
return 0;
}