动态规划合集
动态规划
思想
动态规划是一个通过把原问题分为几个子问题来解决复杂问题的工具。主要有自底向上和自顶向下两种方法。自底向上就是递推,自顶向下就是记忆化递归。
- 什么样的题可以用动态规划来解决?
- 求最优解问题(最大值/最小值)
- 求可行性(
或 ) - 求方案总数
注意:有些问题可以用贪心/排序来解决,就可以不用动态规划。
- 动态规划中的词汇
- 子数组 连续序列中的最优解
- 子序列 可以不是连续的序列中的最优解
动态规划思想例题:
数字三角形
它是一道带有动态规划思想的题目(和递推差不多)
它要求走到底部和最大,我们可以从底部开始推,每次找到下面两个中最大的一个,加到它自己身上,到最后,
for(int i=n-2;i>=0;i--){
for(int j=0;j<=i;j++){
a[i][j]+=max(a[i+1][j],a[i+1][j+1]);
}
}
背包问题
01背包
完全背包
多重背包
混合背包
分组背包
二维费用背包
其它动态规划
经典动态规划问题
编辑距离
我们设
我们能进行的操作有三种
- 在
中插入一个字符 - 在
中插入一个字符 - 修改
中的一个字符
那么这样,就可以得出,状态转移方程为
int left=dp[i-1][j]+1;
int down=dp[i][j-1]+1;
int left_down=dp[i-1][j-1];
if(word1[i-1]!=word2[j-1]){
left_down++;
}
dp[i][j]=min(left,min(left_down,down));
前面再将
class Solution {
public:
int minDistance(string word1, string word2) {
int n=word1.size();
int m=word2.size();
if(n*m==0){
return n+m;
}
vector<vector<int>> dp(n+1,vector<int>(m+1));
for(int i=0; i<=n; i++){
dp[i][0]=i;
}
for(int j=0; j<=m; j++){
dp[0][j]=j;
}
for(int i=1; i<=n; i++){
for(int j=1; j<=m; j++){
int left=dp[i-1][j]+1;
int down=dp[i][j-1]+1;
int left_down=dp[i-1][j-1];
if(word1[i-1]!=word2[j-1]){
left_down++;
}
dp[i][j]=min(left,min(left_down,down));
}
}
return dp[n][m];
}
};
连续子数组最大和
给你一个整数数组
子数组 是数组中的一个连续部分。
比如说一个数组的元素如下:
那么我们可以知道,连续子数组
子数组是要求要是数组里的一段连续的,最大(最小)的一串数字。我们可以用动态规划来求出它。
那么我们可以用
然后,就可以写出式子了。有两中情况,分别是把数字加进去比较大,还有一种就是数字本身比加进去要大(比如说
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int n=nums.size();//注意!vector的size返回的不是一个整形!
vector<int> dp(n+1,0);
int ans=nums[0];
for(int i=1; i<=n; i++){
dp[i]=max(nums[i-1],dp[i-1]+nums[i-1]);
ans=max(ans,dp[i]);
}
return ans;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix