【C++编程能力提升】

代码随想录训练营Day46 | Leetcode 139

  • 一、139 单词拆分
  • 二、多重背包基础
    • 1、定义
    • 2、实质

一、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();
}

你可能感兴趣的:(C++编程,c++,leetcode,动态规划)