代码随想录训练营Day46 | Leetcode 139
一、139 单词拆分
题目链接:139 单词拆分
核心:完全背包问题,背包容量是字符串s,物品是单词表中的所有单词,且是排列问题,并非组合,因为单词组合成字符串s是要求有顺序的。
递推公式:如果字符串在i~j区间的单词在字典中,且背包容量是i时能由单词表单词组合而成,你们背包容量j也可由单词表中单词组合而成。
bool wordBreak(string s, vector<string>& wordDict) {
//完全背包问题:背包容量是s,物品是wordDict的单词元素,且是排列问题,因为组合成字符串s时要求顺序
//dp[j]装满背包容量j时,是否能由wordDict中的单词组成
unordered_set<string> wordSet(wordDict.begin(),wordDict.end()); //便于查找
vector<int> dp(s.size()+1,false);
dp[0]=true; //如果为false,则后续递推的所有值都为false
for(int j=1;j<=s.size();j++)
{//先遍历背包容量,再遍历物品(单词)
for(int i=0;i<j;++i)
{//以i为起点,构造i-j区间的单词,判断是否在字典中
string word=s.substr(i,j-i);
if(dp[i] && wordSet.find(word)!=wordSet.end())
dp[j]=true;
}
}
return dp[s.size()];
}
二、多重背包基础
1、定义
背包容量是V,有N个物品,每个物品存在Mi个相同物品,即可使用Mi次该物品,每个物品的价值是Wi,将物品装入背包使得重量不超过背包容量,且价值最大。
2、实质
多重背包类似01背包,即把Mi个相同物品一一罗列,然后每件物品只能被选择一次,那么多重背包问题就转换成01背包问题。
void test_multi_pack() {
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] > 1) { // nums[i]保留到1,把其他物品都展开
weight.push_back(weight[i]);
value.push_back(value[i]);
nums[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;
}
int main() {
test_multi_pack();
}