1.实践题目:数字三角形
2.问题描述:
给定一个由 n行数字组成的数字三角形如下图所示。试设计一个算法,计算出从三角形 的顶至底的一条路径(每一步可沿左斜线向下或右斜线向下),使该路径经过的数字总和最大。
输入格式:
输入有n+1行:
第 1 行是数字三角形的行数 n,1<=n<=100。
接下来 n行是数字三角形各行中的数字。所有数字在0..99 之间。
输出格式:
输出最大路径的值。
输入样例:
在这里给出一组输入。例如:
5
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出样例:
在这里给出相应的输出。例如:
30
3.算法描述
首先,先写出递归方程式:
{
m[i][j] = a[i][j] i=n;
m[i][j] = m[i+1][j] + m[i+1][j+1] + a[i][j];
再运用动态规划的思想,自下而上求值。
}
代码如下:
#include <iostream>
using namespace std;
int Max(int a,int b){
if(a>=b)
return a;
else
return b;
}
int main()
{
int a[100][100],b[100][100],n;
cin >> n;
for(int i = 0;i < n; i ++ ){
for(int j = 0;j <= i;j ++ ){
cin >> a[i][j];
b[i][j] = a[i][j];
}
}
for(int i = n-2;i >= 0;i -- ){
for(int j = 0;j <= i;j ++ ){
b[i][j] += Max ( b[i+1][j], b[i+1][j+1] );
}
}//自下而上
cout<<b[0][0];
return 0;
}
4.算法时间及空间复杂度分析
时间复杂度:
for(int i = n-2;i >= 0;i -- ){
for(int j = 0;j <= i;j ++ ){
b[i][j] += Max ( b[i+1][j], b[i+1][j+1] );
}
}
由该语句可看得出,依次执行了n-1, n -2, n-3.........1 次。(n-1+1) *n/2 = 1/2n^2
所以时间复杂度:O(n) = n^2
空间复杂度:
由于没有使用辅助的空间,所以空间复杂度是O(1)
5.心得体会
这道题差不多做了一个半小时,一开始以为必须要用递归方法,
结果好不容易做出来也是超时的,也不知道怎么改。其实就是
用备忘录方法和动态规划的思想,自下往上求就是了。由于两
种可能方式都有a[i][j],所以一开始就直接定义一个m数组来
存数值,然后从倒数第二行开始向上求,直接考虑第二种情况
就行了。