7
3 8
8 1 0
2 7 4 4
4 5 2 6 5
在上面的数字三角形中寻找一条从顶部到底边的路径,使得
路径上所经过的数字之和最大。路径上的每一步都只能往正下或
右下走。只需要求出这个最大和即可,不必给出具体路径。
#include <iostream>
using namespace std;
#define MAX 101
// 7
// 3 8
// 8 1 0
// 2 7 4 4
// 4 5 2 6 5
// 在上面的数字三角形中寻找一条从顶部到底边的路径,使得
// 路径上所经过的数字之和最大。路径上的每一步都只能往正下或
// 右下走。只需要求出这个最大和即可,不必给出具体路径。
int D[MAX][MAX]; //D和maxSum数组是101*101正方形状的二维数组
int maxSum[MAX][MAX];//可以先从主函数看起
void DP(int row)
{
for(int i = 1; i <= row; ++i)
{//将D这个二维数组复制给 maxSum这个二维数组
maxSum[row][i] = D[row][i];
}
for(int i = row - 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; //输出最大累加和
}
int main()
{ int b[15] = {7, 3, 8, 8, 1, 0, 2, 7, 4, 4, 4, 5, 2, 6, 5};//按照题目要求先把15个数按照顺序依次存储到b数组里
int c = 0;//再从b数组遍历选取数字依次输入那个二维数组里
for(int i = 1; i <= 5; ++i)
{
for(int j = 1; j <= i; ++j)
{
D[i][j] = b[c];//输入D这个二维数组里
//i是行数,j是列数
++c;
}
}
DP(5);//因为这个三角形只有5层,所以输入为5
return 0;
}
#include<bits/stdc++.h>
using namespace std;
const int N=1e3+10;
int n,a[N][N],dp[N][N];
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
cin>>a[i][j];
}
}
dp[1][1]=a[1][1];
for(int i=1;i<=n;i++){
for(int j=1;j<=i;j++){
dp[i+1][j]=max(dp[i+1][j],dp[i][j]+a[i+1][j]);
dp[i+1][j+1]=max(dp[i+1][j+1],dp[i][j]+a[i+1][j+1]);
}
}
int res=0;
for(int i=1;i<=n;i++)
{
res=max(res,dp[n][i]);
}
cout<<res<<endl;
}
这里的解题关键在于自低向上的迭代结果,不断的删除掉"不可能的数据"开介绍求解的计算量。
从动态规划的条件来论述:
1、最优子结构性质:一个最优化策略的子策略总是最优的。这句可以这么理解,我们知道最大路径必定是先经过顶点的,之后再经过顶点的左、右节点中的一个。因为顶点是固定的,相对于左右子节点来说是一样的,那么如果最大路劲经过的是左节点,那么左节点代表的最优解相对于右节点代表的最优解来说是一个更优解。因为左右子节点就包含了所有的解。所以左节点是最优解。
2、无后效性:每一个状态都代表了过去历史的一个完整总结。
3、子问题的重叠性:动态规划的关键在于解决冗余,本问题中表现出来的就是在向上迭代的过程中,删除了一些不可能成为最优解的数据,从而减少了求解的运算量,并复用了当前“尚且有希望"的解。
创作不易,希望读者多多支持,点赞关注,谢谢