关于 多重背包,力扣上没有相关的题目,所以今天大家的重点就是回顾一波 自己做的背包题目吧。
139.单词拆分
视频讲解:https://www.bilibili.com/video/BV1pd4y147Rh
https://programmercarl.com/0139.%E5%8D%95%E8%AF%8D%E6%8B%86%E5%88%86.html
Tips:因为这道题可能会重复用到单词表中的单词,因此是一个排列问题而不是组合问题,这就需要我们把背包容量放在外层for循环,把元素放在内层for循环。
单词就是物品,字符串s就是背包,单词能否组成字符串s,就是问物品能不能把背包装满。
拆分时可以重复使用字典中的单词,说明就是一个完全背包!
动规五部曲分析如下:
- 确定dp数组以及下标的含义
dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
- 确定递推公式
如果确定dp[j] 是true,且 [j, i] 这个区间的子串出现在字典里,那么dp[i]一定是true。(j < i )。
所以递推公式是 if([j, i] 这个区间的子串出现在字典里 && dp[j]是true) 那么 dp[i] = true。
- 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,只要没有被覆盖说明都是不可拆分为一个或多个在字典中出现的单词。
- 确定遍历顺序
题目中说是拆分为一个或多个在字典中出现的单词,所以这是完全背包。
还要讨论两层for循环的前后顺序。
如果求组合数就是外层for循环遍历物品,内层for遍历背包。
如果求排列数就是外层for遍历背包,内层for循环遍历物品。
我在这里做一个总结:
求组合数:动态规划:518.零钱兑换II (opens new window)求排列数:动态规划:377. 组合总和 Ⅳ (opens new window)、动态规划:70. 爬楼梯进阶版(完全背包) (opens new window)求最小数:动态规划:322. 零钱兑换 (opens new window)、动态规划:279.完全平方数(opens new window)
而本题其实我们求的是排列数,为什么呢。 拿 s = "applepenapple", wordDict = ["apple", "pen"] 举例。
"apple", "pen" 是物品,那么我们要求 物品的组合一定是 "apple" + "pen" + "apple" 才能组成 "applepenapple"。
"apple" + "apple" + "pen" 或者 "pen" + "apple" + "apple" 是不可以的,那么我们就是强调物品之间顺序。
所以说,本题一定是 先遍历 背包,再遍历物品。
我的题解:
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
// dp[i] : 字符串长度为i的话,dp[i]为true,表示可以拆分为一个或多个在字典中出现的单词。
// 完全背包问题
vector<bool> dp(s.size()+1,false);
dp[0] = true;
// 下面是求组合问题的代码,在本题中是不行的
//
// for(int i = 0; i<wordDict.size(); i++){
// for(int j = wordDict[i].size(); j <= s.size(); j++){
// if(dp[j]!=true && dp[j - wordDict[i].size()] == true){
// //substr(起始位置,截取的个数)
// string temp = s.substr(j-wordDict[i].size(), wordDict[i].size());
// if(temp == wordDict[i]){
// dp[j] = true;
// }
// }
// }
// }
for(int j = 0; j<= s.size(); j++){
for(int i = 0; i<wordDict.size(); i++){
if(j >= wordDict[i].size()&& dp[j]!=true && dp[j - wordDict[i].size()] == true){
//substr(起始位置,截取的个数)
string temp = s.substr(j-wordDict[i].size(), wordDict[i].size());
if(temp == wordDict[i]){
dp[j] = true;
}
}
}
}
return dp[s.size()];
}
};
关于多重背包,你该了解这些!
背包问题总结篇!
https://programmercarl.com/%E8%83%8C%E5%8C%85%E6%80%BB%E7%BB%93%E7%AF%87.html
标签:背包,apple,46,单词,wordDict,139,true,dp From: https://www.cnblogs.com/GavinGYM/p/17139272.html