139.单词拆分
题目链接:139.单词拆分
dp
数组含义:字符串长度为 i
能被单词组成,则dp[i] = true
递推公式:有j < i
,如果dp[j] == true && i - j
出现在单词中,dp[i]为true
初始化:dp[0] = true
,其他为false
为了便于对比与字符串和字典中的单词是否重复,因此将vector
容器改成unordered_set
。
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> wordSet(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) {
if (dp[j] && wordSet.find(s.substr(j, i - j)) != wordSet.end()/*判断是否出现在集合中*/)
dp[i] = true;
}
}
return dp.back();
}
};
多重背包
就是有个数的01背包问题。完全背包中物体使用次数是无限制的,多重背包中的物体使用的次数是有限制的,就可以转化为01背包问题。如有物品{a, b, c}
,其中b
有两个,此问题为多重背包问题,因此可以将多重背包问题转化为{a, b, b, c}
为01背包问题。
void test_multipack() {
vector<int> weight = {1, 3, 4};
vector<int> value = {15, 20, 30};
vector<int> nums = {2, 3, 2};
int bagWeight = 10;
for (int i = 0; i < nums.size(); i++) {
while (--nums[i]) { // nums[i]保留到1,把其他物品都展开
weight.push_back(weight[i]);
value.push_back(value[i]);
}
}
vector<int> dp(bagWeight + 1, 0);
for(int i = 0; i < weight.size(); i++) { // 遍历物品
for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
}
for (int j = 0; j <= bagWeight; j++) {
cout << dp[j] << " ";
}
cout << endl;
}
cout << dp[bagWeight] << endl;
}
背包问题总结
最终要的就是根据题意来确认dp数组,通常直接将dp数组表示为最后所求的答案。
通过题意来具体修改递推公式和初始化。
01背包有固定的遍历顺序,完全背包根据背包中的物品顺序是否有序,而选择物品和背包的遍历顺序。
有的题目需要自定义物品或者背包,注意一些细节。