01揹包問題是一種非常經典的動態規劃(\(dp\))的題目。雖然不是很難,但變化靈活,非常重要。
原題是這樣的(稍加改動):
有乙個最多能裝 \(m\) 公斤的揹包,現在有 \(n\) 件物品,它們的重量分別是 \(w_1\),\(w_1\),...,\(w_n\),它們的價值分別為val[1],val[2],...,val[n],求能獲得最大總價值。
動態規劃做題的三大步:
1.定義狀態
2.找出狀態轉移方程
3.找出邊界條件
由於狀態跟容量和物品都有關係,所以dp是二維的。
這道題的狀態就是dp[i][j]是前i個物品放入容量為j的揹包裡所能獲得的最大價值。
狀態轉移方程就很"簡單"了。首先先判斷是否放的下,即if(j>=w[i]),如果放不下,就跟前面一樣的,即dp[i][j]=dp[i-1][j],如果放的下,就max放與不放的價值,即dp[i][j]=max(dp[i-1][j],val[i]+dp[i-1][j-w[i]]),val[i]+dp[i-1][j-w[i]]是因為物品不僅有價值,放進揹包裡還會佔體積。
此題有邊界條件,dp陣列要等於0。
ac**:
#includeusing namespace std;
long long dp[1005][1005],w[1005],val[1005],n,m;
int main()
} cout《注意:j從0開始是因為體積可以為0,輸出dp[n][m]是因為題目說輸出n個物品放入容量為m的揹包裡的最大價值。
類似題目:採藥
01揹包沒有優化前dp陣列是二維,優化後是一維的,具體怎麼優化,先來看乙個**:01
2345
6789
10100
1111
1111
1200
1334
4444
4300
1355
6889
e400
1355
69910
12資料是:
10 40
2 13 3
4 57 9
1234代表前幾個物品,12345678910代表容量。
那麼就會發現dp[i][j]只可能等於d[i-1][j]和dp[i-1][j-1],dp[i-1][j-2]......所以,我們可以倒著迴圈,每一次覆蓋掉前面的。所以可以把物品那一維給去掉,if也可以去掉。
優化**(當作模板背下來就可以啦):
#includeusing namespace std;
long long dp[1005],w[1005],val[1005],n,m;
int main()
dp[0]=1;
for(int i=1;i<=n;i++)
for(int j=m;j>=w[i];j--)
dp[j]=dp[j]+dp[j-w[i]];
cout《還有些題目有兩個容量,只要定義乙個二維dp就可以了,還要一層迴圈,和第二層迴圈一樣,兩個維度的處理也一樣。
題目:p1507
**(帶注釋):
#includeusing namespace std;
long long dp[405][405],w[505],val[505],v[505],v,w,n;
int main()
for(int i=1;i<=n;i++)
for(int j=v;j>=v[i];j--)//迴圈體積
for(int k=w;k>=w[i];k--)//迴圈質量
dp[j][k]=max(dp[j][k],dp[j-v[i]][k-w[i]]+val[i]);
cout
}
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...
揹包問題 01揹包
有n件物品和乙個容量為v的揹包。第i件物品的重量是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。01揹包中的 01 就是一種物品只有1件,你可以選擇放進去揹包即1,也可以選擇不放入揹包中即0。include include using namespace std const int ...
揹包問題(01揹包)
1085 揹包問題 在n件物品取出若干件放在容量為w的揹包裡,每件物品的體積為w1,w2 wn wi為整數 與之相對應的價值為p1,p2 pn pi為整數 求揹包能夠容納的最大價值。input 第1行,2個整數,n和w中間用空格隔開。n為物品的數量,w為揹包的容量。1 n 100,1 w 10000...