如图所示 从顶部出发 计算和最大的数字路径
我的思路:从底部开始,从左右两个数字中挑选最大的值与上一个数值相加
依次向上递推,最终求得最大值
存在的问题:存在重复计算 如底部的5和6 会被重复利用计算 浪费时间空间
动态规划思路:
创建一个与该数字三角矩阵规模一致的镜像矩阵 用来存储计算过的值 在下一次牵涉到重复计算时,直接取出计算即可
代码:
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<time.h>
using namespace std;
#define MaxSize 101
int saveMaxSum[MaxSize][MaxSize];
int D[MaxSize][MaxSize];
int n = 0; //行数
void main() {
srand(time(NULL));
cin >> n; //表示三角形有多少行
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= i; ++j) {
D[i][j] = rand() % 100;
saveMaxSum[i][j] = -1;
}
//动态递推
//先处理最后一行
for (int k = 1; k <= n; ++k) {
saveMaxSum[n][k] = D[n][k]; //先将最后一行赋值
}
for (int i = n-1; i >= 1; --i) { //从倒数第二行开始计算
for (int j = 1; j <= i; ++j) {
saveMaxSum[i][j] = max(saveMaxSum[i + 1][j], saveMaxSum[i + 1][j + 1]) + D[i][j]; //将每一行的计算结果保留 用于下一次计算
}
}
cout << saveMaxSum[1][1] << endl;
system("PAUSE");
return;
}
思路:将每一行的计算结果进行保留 在下一次计算时取出复用
这样就避免了重复计算
由这个例子看动态规划:
递归就是将原问题分解成多个子问题,然后进行逆推的过程
将原问题分解成若干个子问题 子问题和原问题形式类似或相同 子问题全部解决 原问题就解决了
该例子问题:第i行第j列 正下方到底边的最大值 和 右下方到底边的最大值
确定状态:数字所代表的行号和列号就是状态
三角形中 初始状态就是三角形底边数字 值就是底边数字的值
通过值已知的状态递推值未知的状态
转移方程:
已知值得状态(底层,起始点):
saveMaxSum[i][j] = D[i][j]
未知值的状态:
saveMaxSum[i][j] = max(saveMaxSum[i + 1][j], saveMaxSum[i + 1][j + 1]) + D[i][j];