Day46 动规 139

24 阅读2分钟

139. 单词拆分

心得

  • 字典是物品,目标的结果是背包,考虑装满背包时想的是字符串拼接或者个数等不等,没有好好利用string 查找函数和用set保存的快速检索

题解

  • 排列问题,背包在外循环,物品在内循环,初始值取有迭代意义的值,不一定需要实际意义
class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        vector<bool> dp(s.size() + 1, false);  // dp[i] 表示字符串长度为i时,true表示能被字典拆分
        unordered_set<string> wordSet(wordDict.begin(), wordDict.end());
        dp[0] = true; 
        for (int i = 1; i <= s.size(); i++) { // 先背包,后物品
            for (int j = 0; j < i; j++) { // 一般完全背包循环条件能写到=,但是考虑到substr的函数,没有写到
                string word = s.substr(j, i - j); // substr(开始位置,长度)
                if (wordSet.find(word) != wordSet.end() && dp[j] == true) {
                    dp[i] = true;
                }
            }
        }
        return dp[s.size()];  
    }
};

多重背包

  • 在01背包的基础上,每个物品的个数有nums组成,这也暗示其求解办法可以将01背包的value和weight扩容

题解

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

背包问题总结

按照递归五部曲来选择(每个都很重要,递推公式遍历顺序一般有模板)

  1. 确定dp数组含义,下标含义和dp[i]数值含义
  2. 递推公式
  3. 初始化
  4. 遍历顺序
  5. 打印,确认dp数组

01背包

  • 容量V的背包,物品N种,每个仅一个,提供weight和value,每次选或者不选01问题
  • 2维dp数组时,遍历顺序先物品还是背包都可以,但是第二层需要从小到大(后一个由上和左上角推出)
  • 一维dp数组只能先物品后背包容量,且第二层从大到小(保证不被覆盖)

完全背包

  • 容量V的背包,物品N种,每种无限个,提供weight和value,每次不选或者选多个
  • 纯完全背包问题,遍历顺序先物品还是背包都可以的且第二层循环小到大,但是题目稍微变化即对遍历有要求
  • 组合数:外层物品,内层背包容量
  • 排列数:外层背包容量,内层物品

递推公式

求最值一般max或min,恰好的所需办法一般求和