【代码随想录】41

6

2023年10月24日 - 动态规划8

139. 单词拆分

完全背包的思路解决

 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++) {       // 遍历物品
                 string word = s.substr(j, i - j); //substr(起始位置,截取的个数)
                 if (wordSet.find(word) != wordSet.end() && dp[j]) {
                     dp[i] = true;
                 }
             }
         }
         return dp[s.size()];
     }
 };

背包问题总结

递推公式

纯完全背包类问题,先遍历物品还是先遍历背包可以颠倒的

能否装满背包(或最多装多少)

递推公式 dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);

如果求装满背包有多少种方法,就要区分求组合数还是排列数

如果求组合数就是外层for循环遍历物品,内层for遍历背包。这样子就不会重复

如果求排列数就是外层for遍历背包,内层for循环遍历物品。

内层从大到小还是从小到大取决于是否可以重复取

递推公式 dp[j] += dp[j - nums[i]]

问背包装满最大价值

递推公式 dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

问装满背包所有物品的最小个数

递推公式 dp[j] = min(dp[j - coins[i]] + 1, dp[j]);

遍历顺序

01背包

动态规划:关于01背包问题,你该了解这些! (opens new window)中我们讲解二维dp数组01背包先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

动态规划:关于01背包问题,你该了解这些!(滚动数组) (opens new window)中,我们讲解一维dp数组01背包只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。

完全背包

动态规划:关于完全背包,你该了解这些! (opens new window)中,讲解了纯完全背包的一维dp数组实现,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

相关题目如下:

如果求最小数,那么两层for循环的先后顺序就无所谓了,相关题目如下: