一·、单词划分

给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

分析如下:

动规五部曲分析如下:

1.确定dp数组以及下标的含义

dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词

2.确定递推公式

如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。

所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。

3.dp数组如何初始化

从递推公式中可以看出,dp[i] 的状态依靠 dp[j]是否为true,那么dp[0]就是递推的根基,dp[0]一定要为true,否则递推下去后面都都是false了。

那么dp[0]有没有意义呢?

dp[0]表示如果字符串为空的话,说明出现在字典里。

但题目中说了“给定一个非空字符串 s” 所以测试数据中不会出现i为0的情况,那么dp[0]初始为true完全就是为了推导公式。

下标非0的dp[i]初始化为false,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词。

4.确定遍历顺序

题目中说是拆分为一个或多个在字典中出现的单词,所以这是完全背包。

还要讨论两层for循环的前后顺序。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

本题一定是 先遍历 背包,再遍历物品。

5.举例推导dp[i]

代码如下:

class Solution {
public:bool wordBreak(string s, vector<string>& wordDict) {unordered_set<string> workSet(wordDict.begin(),wordDict.end());vector<bool> dp(s.size()+1,false);dp[0]=true;for(int i=1;i<=s.size();i++){for(int j=0;j<i;j++){string word=s.substr(j,i-j);if(workSet.find(word)!=workSet.end()&&dp[j]){dp[i]=true;}}}return dp[s.size()];}
};

二、多重背包

有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。

多重背包和01背包是非常像的, 为什么和01背包像呢?

每件物品最多有Mi件可用,把Mi件摊开,其实就是一个01背包问题了。

多重背包力扣上没有原题,所以菜菜去acwing上刷一题看看

代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N=110;
int n,m;
int v[N],w[N],s[N];
int dp[N][N];
int main()
{cin>>n>>m;for(int i=1;i<=n;i++) cin>>v[i]>>w[i]>>s[i];for(int i=1;i<=n;i++){for(int j=0;j<=m;j++){for(int k=0;k<=s[i]&&k*v[i]<=j;k++){dp[i][j]=max(dp[i][j],dp[i-1][j-v[i]*k]+k*w[i]);   }}}cout<<dp[n][m]<<endl;return 0;
}

三、背包总结

动态规划必须分为5步进行,切记切记

背包问题总结:

递推公式

问能否能装满背包(或者最多装多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]); ,对应题目如下:

  • 动态规划:416.分割等和子集(opens new window)
  • 动态规划:1049.最后一块石头的重量 II(opens new window)

问装满背包有几种方法:dp[j] += dp[j - nums[i]] ,对应题目如下:

  • 动态规划:494.目标和(opens new window)
  • 动态规划:518. 零钱兑换 II(opens new window)
  • 动态规划:377.组合总和Ⅳ(opens new window)
  • 动态规划:70. 爬楼梯进阶版(完全背包)(opens new window)

问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); ,对应题目如下:

  • 动态规划:474.一和零(opens new window)

问装满背包所有物品的最小个数:dp[j] = min(dp[j - coins[i]] + 1, dp[j]); ,对应题目如下:

  • 动态规划:322.零钱兑换(opens new window)
  • 动态规划:279.完全平方数

递归顺序 

01背包

在动态规划:关于01背包问题,你该了解这些! (opens new window)中我们讲解二维dp数组01背包先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

和动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中,我们讲解一维dp数组01背包只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。

一维dp数组的背包在遍历顺序上和二维dp数组实现的01背包其实是有很大差异的,大家需要注意!

#完全背包

说完01背包,再看看完全背包。

在动态规划:关于完全背包,你该了解这些! (opens new window)中,讲解了纯完全背包的一维dp数组实现,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

但是仅仅是纯完全背包的遍历顺序是这样的,题目稍有变化,两个for循环的先后顺序就不一样了。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

相关题目如下:

  • 求组合数:动态规划:518.零钱兑换II(opens new window)
  • 求排列数:动态规划:377. 组合总和 Ⅳ (opens new window)、动态规划:70. 爬楼梯进阶版(完全背包)(opens new window)

如果求最小数,那么两层for循环的先后顺序就无所谓了,相关题目如下:

  • 求最小数:动态规划:322. 零钱兑换 (opens new window)、动态规划:279.完全平方数(opens new window)

对于背包问题,其实递推公式算是容易的,难是难在遍历顺序上,如果把遍历顺序搞透,才算是真正理解了

代码随想录算法训练营第四十六天|139.单词拆分、多重背包、背包问题总结篇相关推荐

  1. 代码随想录算法训练营第五十六天-动态规划16|● 583. 两个字符串的删除操作 ● 72. 编辑距离 ● 编辑距离总结篇

    一.583. 两个字符串的删除操作 给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符. 示例: 输入: &qu ...

  2. _42LeetCode代码随想录算法训练营第四十二天-动态规划 | 121.买卖股票的最佳时机、122.买卖股票的最佳时机II

    _42LeetCode代码随想录算法训练营第四十二天-动态规划 | 121.买卖股票的最佳时机.122.买卖股票的最佳时机II 题目列表 121.买卖股票的最佳时机 122.买卖股票的最佳时机II 1 ...

  3. 代码随想录算法训练营第五十天|动态规划:139.单词拆分、多重背包理论基础、背包问题总结

    [139.单词拆分] 这个题目是一个背包问题.但是他稍微有点不太一样.在于这题判断能否装满背包是在判断单词是否出现在字典中,如果出现,就代表能装满. 背包是长度为i的字符串 物品是长度为i-j的子串 ...

  4. 代码随想录算法训练营第三十天| LeetCode332. 重新安排行程、LeetCode51. N 皇后、LeetCode37. 解数独

    一.LeetCode332. 重新安排行程 1:题目描述(32. 重新安排行程) 给你一份航线列表 tickets ,其中 tickets[i] = [fromi, toi] 表示飞机出发和降落的机场 ...

  5. 代码随想录算法训练营第四十二天 | 01背包问题,你该了解这些、01背包问题,你该了解这些 滚动数组、 416. 分割等和子集

    打卡第42天,搞搞01背包. 今日任务 01背包问题,你该了解这些! 01背包问题,你该了解这些! 滚动数组 416.分割等和子集 背包问题1.0 :0-1 背包 有n件物品和一个最多能背重量为w 的 ...

  6. 代码随想录算法训练营第四十三天 | 填满背包有几种方法、背包有两个维度

    1049.最后一块石头的重量II 文档讲解:代码随想录 (programmercarl.com) 视频讲解:动态规划之背包问题,这个背包最多能装多少?LeetCode:1049.最后一块石头的重量II ...

  7. 代码随想录算法训练营第四期第六天| 454.四数相加II、383.赎金信、15.三数之和、18. 四数之和

    454.四数相加II 给你四个整数数组nums1.nums2.nums3和nums4 ,数组长度都是n ,请你计算有多少个元组(i, j, k, l)能满足: 0 <= i, j, k, l & ...

  8. 代码随想录算法训练营第三十天| 第七章 回溯算法:332.重新安排行程,51.N皇后,37.解数独(python)

    回溯算法总结 332.重新安排行程 讲解链接 class Solution:def __init__(self):self.res = []self.dict = defaultdict(list)d ...

  9. 代码随想录算法训练营第三十天| 332.重新安排行程(跳过)、51. N皇后 、37. 解数独

    Leetcode - 51 首先这道题不同于以往的是,这是处理一个二维序列,前面我们都处理的是一维的,那么二维序列的话我们就要用两个for吗?其实这里不用,因为在每一行里,我们只要找到一个适合的位置放 ...

最新文章

  1. 为栈实现高效的max操作
  2. php随机数、时间、字符串函数,正则,数组函数
  3. Hacker:编写高级语言脚本可破解各个云盘的下载速度限制
  4. mysql 知识整理(待续)
  5. 第一个Android程序
  6. Symfony1.4.11学习笔记(四):数据模型
  7. AppStore图片尺寸以及内容要求Screenshot specifications
  8. 【笔记】android应用签名
  9. 软考系统分析师备考详细介绍
  10. Ecshop小京东支付插件【小京东个人支付宝即时到帐支付插件支持PC电脑版+手机版】
  11. 如何禁止Windows自动更新AMD显卡驱动
  12. 微信公众号的简单开发
  13. Android带数字拼音与带音标拼音互转工具类
  14. 视频教程-Scratch趣味编程课堂-L1-其他
  15. Linux 执行新程序:execve() 函数
  16. 顾大嫂贴肉藏了尖刀 水浒传
  17. 数据系统架构-6.BI数据展示平台
  18. Watering Grass UUV 1038 贪心
  19. c++语言编的小游戏,用C++语言编写小游戏系统(可读取文件)
  20. matlab函数exp,Matlab基本函数-exp函数

热门文章

  1. 计算机运行内存是什么,电脑的“内存”和手机的“运行内存”是一回事吗?有什么区别?...
  2. macos 安装nginx
  3. delphi Align属性
  4. 办上海居住证时需要的居委会证明和亲戚证明格式
  5. 登录+上传头像+瀑布流 (OKhttp+recycleview)
  6. 新手入门必备,分享5个自媒体实用工具,效率和收益都翻倍
  7. IMDB-WIKI - 具有年龄和性别标签的500k +脸部图像
  8. git errno 10054
  9. cdn搭建原理_一文搞懂CDN加速原理
  10. 将UEditor的图片批量上传抠出来单独使用