算法学习->求解三角形最小路径及其值
00 问题
00-1 描述
【算法学习->求解三角形最小路径及其值】对给定高度为n的一个整数三角形,找出从顶部到底部的最小路径和。每个整数只能向下移动到与之相邻的整数。
找到一个一样的力扣题:120. 三角形最小路径和 - 力扣(LeetCode) (leetcode-cn.com)
示例1:
输入:triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
输出:11
解释:如下面简图所示:
2
3 4
6 5 7
4 1 8 3
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。
示例2:
输入:triangle = [[-10]]
输出:-10
00-2 提示:
1 <= triangle.length <= 200
triangle[0].length == 1
triangle[i].length == triangle[i - 1].length + 1
-104 <= triangle[i][j] <= 104
01 思路 想用动态规划写出来,重点在于状态转移方程。
将等腰三角形抽象为等腰直角三角形,如下
0 1 2 3
0 2
1 3 4
2 6 5 7
3 8 3 9 2
加上下标化的序列,我们就可以用二维数组dp来考虑。dp是用来存储到i,j位置后用到的最短路径长度,比如dp[2] [2]=2+4+7=13
定义一个起点:
dp[0][0] = a[0][0];
三种情况:
- 三角形左路,在直角图里就是第一列,满足:
dp[i][0]=dp[i-1][0];
- 三角形右路,在直角图里是对角线,满足:
dp[i][i]=dp[i-1][i-1]+a[i][i]
- 普通位置
dp[i][j]=min(dp[i-1][j-1],dp[i-1][j])+a[i][j];
02 代码
class Solution {
public:
int minimumTotal(vector>& triangle) {
int len = triangle.size();
int dp[200][200]={0};
dp[0][0]=triangle[0][0];
for(int i=1; idp[i][0] = dp[i-1][0]+triangle[i][0];
}
for(int i=1; idp[i][i] = triangle[i][i]+dp[i-1][i-1];
}
for(int i=2; ifor(int j=1; jdp[i][j] = triangle[i][j]+min(dp[i-1][j], dp[i-1][j-1]);
}
}
//填充dp
//下面筛选路径最短
int ans = dp[len-1][0];
for(int j = 1; j < len; j++){
if(dp[len-1][j]ans = dp[len-1][j];
}
}
return ans;
}
};
03 升级版--记录路径 03-1 思路
如果要记下路径,需要再来一个二维数组pre来记录坐标为i,j的点的前一个节点。那么如何记录呢?我们看一下:
- (i,i)的前一个节点就是(i-1,i-1);
- (i,j)的前一个节点是(i-1,j)或者(i-1,j-1);
- (i,0)的前一个节点是(i-1,0)。
记录之后,我们还需要输出这个最小路径。怎么输出呢?
我们在前一问题的基础上得到最后行的最小值的列值后,将它返回主控函数,并用它作为参数给路径输出函数Disppath。
输出方法为:
- 对于当前节点,入栈,查它的pre数组值,更新,继续该操作,直到完成。
更新操作为:
path.push_back(a[i][k]);
k=pre[i][k];
- 逐个出栈。
03-2 代码
//三角形最小路径
#include
#include
#include
using namespace std;
#define MAXN 100
int a[MAXN][MAXN]; //三角形
int n; //高度
int ans = 0; //应求的路径长度
int dp[MAXN][MAXN];
int pre[MAXN][MAXN]; //前驱结点
//根据状态转移方程,只记录列号即可
int Search(){
int i,j;
dp[0][0] = a[0][0];
for(i=1; idp[i][0]=dp[i-1][0]+a[i][0];
pre[i][0]=i-1;
}
for(i=1; idp[i][i]=dp[i-1][i-1]+a[i][i];
pre[i][i]=i-1;
}
for(i=2; ifor(j=1; jif(dp[i-1][j-1] dp[i][j]=dp[i-1][j-1]+a[i][j];
pre[i][j]=j-1;
}
else{
dp[i][j]=dp[i-1][j]+a[i][j];
pre[i][j]=j;
}
}
}
ans = dp[n-1][0];
int k=0;
for ( j = 1; j < n; j++)
{
if(ans>dp[n-1][j]){
ans = dp[n-1][j];
k=j;
}
}
return k;
}
void Disppath(int k){
int i=n-1;
vectorpath; //路径节点
while(i>=0){
path.push_back(a[i][k]);
k=pre[i][k];
i--;
}
vector::reverse_iterator it;
for(it=path.rbegin(); it!=path.rend(); ++it){
printf("%d ",*it);
}
printf("\n");
}
?
int main(){
int k; //k行k列的三角形
memset(pre, 0, sizeof(pre));
memset(dp, 0, sizeof(dp));
scanf("%d",&n);
for(int i=0; ifor(int j=0; j<=i; j++){
scanf("%d",&a[i][j]);
}
}
k=Search();
Disppath(k);
printf("%d\n",ans);
return 0;
}
?
推荐阅读
- 由浅入深理解AOP
- 继续努力,自主学习家庭Day135(20181015)
- python学习之|python学习之 实现QQ自动发送消息
- 画解算法(1.|画解算法:1. 两数之和)
- Guava|Guava RateLimiter与限流算法
- 一起来学习C语言的字符串转换函数
- 定制一套英文学习方案
- 漫画初学者如何学习漫画背景的透视画法(这篇教程请收藏好了!)
- 《深度倾听》第5天──「RIA学习力」便签输出第16期
- 如何更好的去学习