**leetcode題解回答:[jackie.yl]
常見的揹包問題分為三種:
組合問題公式
dp[i]
+= dp[i-num]
true、false問題公式
dp[i]
= dp[i]
or dp[i-num]
最大最小問題公式
dp[i]
=min
(dp[i]
, dp[i-num]+1
)或者dp[i]
=max
(dp[i]
, dp[i-num]+1
)
以上三組公式是解決對應問題的核心公式。
當然拿到問題後,需要做到以下幾個步驟:
1.分析是否為揹包問題。
2.是以上三種揹包問題中的哪一種。
3.是0-1揹包問題還是完全揹包問題。也就是題目給的nums陣列中的元素是否可以重複使用。
4.如果是組合問題,是否需要考慮元素之間的順序。需要考慮順序有順序的解法,不需要考慮順序又有對應的解法。
接下來講一下揹包問題的判定
揹包問題具備的特徵:給定乙個target,target可以是數字也可以是字串,再給定乙個陣列nums,nums中裝的可能是數字,也可能是字串,問:能否使用nums中的元素做各種排列組合得到target。
揹包問題技巧:
1.如果是0-1揹包,即陣列中的元素不可重複使用,nums放在外迴圈,target在內迴圈,且內迴圈倒序;
for num in nums:
for i in range
(target, nums-1,
-1):
2.如果是完全揹包,即陣列中的元素可重複使用,nums放在外迴圈,target在內迴圈。且內迴圈正序。
for num in nums:
for i in range
(nums, target+1)
:
3.如果組合問題需考慮元素之間的順序,需將target放在外迴圈,將nums放在內迴圈。
for i in range(1
, target+1)
:for num in nums:
例題:
組合注意區分零錢兌換||與組合總和4兩個問題是不一樣的,零錢兌換對組合順序無要求,而組合總和對組合順序還有要求不同也算,而這種不同只需要**進行內外層迴圈互換一下即可。
518. 零錢兌換 ii
class
solution
}return dp[amount];}
};
494. 目標和
這個題還是比較神奇的,換乙個角度來看這道題轉化為了乙個標準的01揹包問題:
把所有符號為正的數總和設為乙個揹包的容量,容量為x;把所有符號為負的數總和設為乙個揹包的容量,容量為y。在給定的陣列中,有多少種選擇方法讓揹包裝滿。令sum為陣列的總和,則x+y = sum。而兩個揹包的差為s,則x-y=s。從而求得x=(s+sum)/2。
基於上述分析,題目轉換為揹包問題:給定乙個陣列和乙個容量為x的揹包,求有多少種方式讓揹包裝滿。
class
solutionif(
(s+sum)%2
!=0)return0;
if(s>sum)
return0;
long
long len =
(s+sum)/2
;long
long
* dp =
newlong
long
[len+1]
;//dp陣列的意義為使用nums的數湊成的方法數
//int dp[len+1] = ;
memset
(dp,0,
sizeof
(long
long)*
(len+1)
);dp[0]
=1;for
(int i =
0;i!=nums.
size()
;i++)}
return dp[len];}
};
377. 組合總和 ⅳ
class
solution
}return dp[target];}
};
最大值最小值問題
474. 一和零
dp陣列含義:dp[i][j代表使用i個0與j個1所能拼出的最多的字串數量
class
solution
}for
(int k =
0;k!=strs.
size()
;k++)}
}return dp[m]
[n];}}
;
322. 零錢兌換
求最小數量,min
當 i0i0 時無法用硬幣組成,為 0 。當 i<0i<0 時,忽略 f(i)f(i)
f(i) 最小硬幣數量
f(0) 0 //金額為0不能由硬幣組成
f(1) 1 //f(1)=min(f(1-1),f(1-2),f(1-5))+1=1f(1)=min(f(1−1),f(1−2),f(1−5))+1=1
f(2) 1 //f(2)=min(f(2-1),f(2-2),f(2-5))+1=1f(2)=min(f(2−1),f(2−2),f(2−5))+1=1
f(3) 2 //f(3)=min(f(3-1),f(3-2),f(3-5))+1=2f(3)=min(f(3−1),f(3−2),f(3−5))+1=2
f(4) 2 //f(4)=min(f(4-1),f(4-2),f(4-5))+1=2f(4)=min(f(4−1),f(4−2),f(4−5))+1=2
… …f(11) 3 //f(11)=min(f(11-1),f(11-2),f(11-5))+1=3f(11)=min(f(11−1),f(11−2),f(11−5))+1=3
class
solution
}return dp[amount]
>=amount+1?
-1:dp[amount];}
};
ture false 問題
416. 分割等和子集
這個不能求子集,測試用例會卡住,dp直接照搬給出的套路即可,這是乙個01揹包問題湊數,記得在前面加上陣列和的判定可以直接返回false。dp陣列的含義為dp[i]該子集能否湊出i
class
solution
if(sum%2==
1)return
false
; vector<
bool
>
dp(sum/2+
1,false);
dp[0]
=true
;for
(int i =
0;i!=nums.
size()
;i++)}
//vectortrack;
//backtrack(nums,0,0,sum);
return dp[sum/2]
;}};
139. 單詞拆分
dp陣列的含義為dp[i],s的前i個字元能否能夠由字典裡的字串組成。
class
solution
return1;
}bool
wordbreak
(string s, vector
& worddict)
}//return check(0,worddict[0],s);
return dp[n];}
};
DP 揹包問題
大牛 以下使用滾到陣列 若輸入要求一般,可以邊定義狀態邊輸入,不需儲存 memset f,0,sizeof int n 若求最小值,除 f 0 其餘初始化為 inf,f 0 0是必須的 求最大最小都一樣 確保有從無到有的起點 0 1揹包 一般形式 f i v max f i 1 v f i 1 v ...
揹包問題 DP
01揹包 現在有1個體積為mmax的揹包和n種物品 每種物品只有1個 每種物品的體積和價值分別是v i 和w i 求這個揹包最多可以裝價值多少的物品。這是最基礎的揹包問題,特點是 每種物品僅有一件,可以選擇放或不放。用子問題定義狀態 設f i j 表示前i件物品恰放入乙個容量為j的揹包可以獲得的最大...
DP 揹包問題
小明同學在參加一場考試,考試時間2個小時。試卷上一共有n道題目,小明要在規定時間內,完成一定數量的題目。考試中不限制試題作答順序,對於 i 第道題目,小明有三種不同的策略可以選擇 1 直接跳過這道題目,不花費時間,本題得0分。2 只做一部分題目,花費pi分鐘的時間,本題可以得到ai分。3 做完整個題...