單詞拆分
題目連結:139. 單詞拆分 - 力扣(LeetCode)
思路:竟然真能轉化為揹包問題。
class Solution {
public:
bool wordBreak(string s, vector<string>& wordDict) {
unordered_set<string> t(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(t.find(word)!=t.end()&&dp[j]){
dp[i]=true;
}
}
}
return dp[s.size()];
}
};
關於多重揹包,你該瞭解這些!
多重揹包和01揹包的區別在於一件物品能用多次,且不是不限次。一種處理方法,是將可多次使用的物品當做不同的物品,因此將問題轉化為01揹包問題。如
for (int i = 0; i < n; i++) {
while (nums[i] > 1) { // 物品數量不是一的,都展開
weight.push_back(weight[i]);
value.push_back(value[i]);
nums[i]--;
}
}
但這個方法由於vector的動態擴容十分耗時。還有一種處理方式,就是放到for迴圈裡再遍歷一輪
for(int i = 0; i < n; i++) { // 遍歷物品
for(int j = bagWeight; j >= weight[i]; j--) { // 遍歷揹包容量
// 以上為01揹包,然後加一個遍歷個數
for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍歷個數
dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]);
}
}
}
揹包問題總結篇!
程式碼隨想錄 (programmercarl.com)
揹包遞推公式
- 問能否能裝滿揹包(或者最多裝多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
- 問裝滿揹包有幾種方法: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揹包
二維dp陣列01揹包先遍歷物品還是先遍歷揹包都是可以的,且第二層for迴圈是從小到大遍歷。一維dp陣列01揹包只能先遍歷物品再遍歷揹包容量,且第二層for迴圈是從大到小遍歷。
完全揹包
純完全揹包的一維dp陣列實現,先遍歷物品還是先遍歷揹包都是可以的,且第二層for迴圈是從小到大遍歷。
但是僅僅是純完全揹包的遍歷順序是這樣的,題目稍有變化,兩個for迴圈的先後順序就不一樣了。
如果求組合數就是外層for迴圈遍歷物品,內層for遍歷揹包。
如果求排列數就是外層for遍歷揹包,內層for迴圈遍歷物品。