题目链接:[ POJ - 1163 ]
题目大意
用二维数组存放数字三角形。
D(r, j)
: 第r行第j个数字(r, j从1开始算)
MaxSum(r, j)
: 从D(r, j)
到底边的各条路径中,最佳路径的数字之和。
问题:求 MaxSum(1, 1)
思路
典型的递归问题。
D(r, j)
出发,下一步只能走 D(r+1,j)
或者 D(r+1, j+1)
。故对于N行的三角形:
if ( r == N)
MaxSum(r,j) = D(r,j)
else
MaxSum( r, j) = Max{ MaxSum(r+1,j), MaxSum(r+1,j+1) } + D(r,j)
但是!会超时!
如果每算出一个 MaxSum(r,j)
就保存起来,下次用到其值的时候直接取用,则可免去重复计算。
那么可以用 $O(n^2)$ 时间完成计算。因为三角形的数字总 数是 $n(n+1) {\div} 2$
然后我们将递归转化为递推即可,之后进行空间优化:
没必要用二维maxSum数组存储每一个 MaxSum(r,j)
,只要从底层一行行向上递推,
那么只要一维数组maxSum[100]即可,即只要存储一行的MaxSum值就可以。
题解代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 100 + 10;
int dp[maxn];
int map[maxn][maxn];
int main(void)
{
int n;
cin >> n;
for(int i = 1; i <= n; i++)
for(int j = 1; j <= i; j++)
scanf("%d", &map[i][j]);
for(int i = 1; i <= n; i++)
dp[i] = map[n][i];
for(int i = n - 1; i > 0; i--)
for(int j = 1; j <= i; j++)
dp[j] = max(dp[j], dp[j+1]) + map[i][j];
cout << dp[1] << endl;
return 0;
}