您的位置:首页 > 其它

动态规划之数字三角形

2017-03-30 11:00 274 查看
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的数字三角形中寻找一条从顶部到底边的路径,使得路径上所经过的数字之和最大。路径上的每一步只能往左下或右下走。只需要求出这个最大和即可,不必给出具体路径,
三角形的行数大于1小于等于100,数字为0-99.
输入:
5//行数
7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
输出:
最大和

解题思路:
用二维数组存放数字三角形。
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);


代码如下:

#include<iostream>
#include<algorithm>
#define MAX 101
using namespace std;
int D[MAX][MAX];
int n;
int MaxSum(int i, int j) {
if (i == n)
return D[i][j];
int x = MaxSum(i + 1, j);
int y = MaxSum(i + 1, j + 1);
return max(x, y) + D[i][j];
}
int main() {
int i, j;
cin >> n;
for (i = 1; i <= n; i++)
for (j = 1; j <= i; j++) {
cin >> D[i][j];
}
cout << MaxSum(1, 1) << endl;
}


但是,上述的递归方法时间复杂度太大,为2的n次方,不可取。

因此,选择记忆递归型动归程序,其时间复杂度为n的2次方。

#include<iostream>
#include<algorithm>
#define MAX 101
using namespace std;
int D[MAX][MAX];
int maxSum[MAX][MAX];
int n;
int MaxSum(int i, int j) {
if (maxSum[i][j] != -1)
return maxSum[i][j];
if (i == n)
return D[i][j];
int x = MaxSum(i + 1, j);
int y = MaxSum(i + 1, j + 1);
return max(x, y) + D[i][j];
}
int main() {
int i, j;
cin >> n;
for (i = 1; i <= n; i++)
for (j = 1; j <= i; j++) {
cin >> D[i][j];
maxSum[i][j] = -1;
}
cout << MaxSum(1, 1) << endl;
}


将动归程序转成递推程序:

#include<iostream>
#include<algorithm>
#define MAX 101
using namespace std;
int D[MAX][MAX];
int maxSum[MAX][MAX];
int n;
int main() {
int i, j;
cin >> n;
for (i = 1; i <= n; i++)
for (j = 1; j <= i; j++)
cin >> D[i][j];
for (int i = 1; i <= n; ++i)
maxSum
[i] = D
[i];
for (int i = n - 1; i >= 1; --i)
for (int j = 1; j <= i; ++j)
maxSum[i][j] = max(maxSum[i + 1][j], maxSum[i + 1][j + 1]) + D[i][j];
cout << maxSum[1][1] << endl;
}


进一步进行空间优化
没必要用二维maxSum数组存储每一个MaxSum(r,j),只要从底层一行行向上递推,那么只要一维数组maxSum[100]即可,即只要存储一行的MaxSum值就可以。
进一步考虑,连maxSum数组都可以不要,直接用D的第n行代替maxSum即可。节省空间,时间复杂度


#include<iostream>
#include<algorithm>
#define MAX 101
using namespace std;
int D[MAX][MAX];
int * maxSum;
int n;
int main() {
int i, j;
cin >> n;
for (i = 1; i <= n; i++)
for (j = 1; j <= i; j++)
cin >> D[i][j];
maxSum = D
;
for (int i = n - 1; i >= 1; --i)
for (int j = 1; j <= i; ++j)
maxSum[j] = max(maxSum[j], maxSum[j + 1]) + D[i][j];
cout << maxSum[1] << endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: