有n件物品和乙個大小為m的揹包,以及若干物品,每種物品只有一件,大小分別為w[i],其價值分別為val[i]。問題:將哪些物品裝入揹包,可使得揹包內的物品價值總和最大?由於每種物品都只有一件,所以只存在兩個選擇:裝這個物品或者不裝。(也就是0/1揹包的含義)輸入:第一行:n m
接下來n行,每行兩個整數,w[i]和val[i]。
輸出:最大價值vmax.
我們定義乙個陣列bag [i] [v]用於儲存——當揹包大小為v,且選擇處理完第i個物品後(前i個物品選擇裝或不裝)的最大價值總和,那麼最終的答案就是bag [n] [m]。
我們通過乙個例子來推出bag [i] [v]的遞推式。
有3個物品,大小價值如下表,和乙個大小為3的揹包。
物品/揹包大小12
3a,大小1,價值2
b,大小2,價值5
c,大小1,價值3
先考慮裝不裝a。如下表。
物品/揹包大小12
3a,大小1,價值222
2b,大小2,價值5
c,大小1,價值3
由於a的大小只有1,所以大小1~3的揹包都可以裝下它,於是更新所有值為a的價值2。
接下來考慮b。如下表。
物品/揹包大小12
3a,大小1,價值222
2b,大小2,價值525
7c,大小1,價值3
由於b的大小為2,所以大小為1的揹包裝不下它,值不變。
大小為2的揹包可裝下它,且值為5,比原來的2大,於是更新值為5。
大小為3的揹包可裝下它,且裝完後剩餘大小為1。
如果裝b,那麼價值=b的價值+未裝b的、大小為1的揹包的最大價值=5+2=7。
如果不裝b,那麼價值就是原來的值=2。在二者裡取max,就能得到最大值,也就是7。
最後考慮c。如下表。
物品/揹包大小12
3a,大小1,價值222
2b,大小2,價值525
7c,大小1,價值335
8c的大小為1,揹包1可裝,值更大,更新為3。
揹包2可裝,如果裝,那麼價值=c的價值+未裝c的、大小為1的揹包的最大價值=3+2=5。
如果不裝,值就是原來的5。二者取max即可。
揹包3可裝,如果裝,那麼價值=c的價值+未裝c的、大小為2的揹包的最大價值=5+3=8。
如果不裝,值就是原來的7。二者取max即可。
所以最後輸出的值就是8。
小結論:
我們可以發現遞推公式:bag [i] [v] = max ( bag [i-1] [v] , bag [i-1] [ v - w [i] ] + val [i] )。
也就是處理第i件物品,揹包大小為v時的最大價值,有兩種可能。
①裝入第i件物品
那麼價值=該物品的價值+未裝入該物品的、大小足夠塞入該物品的揹包的最大價值=bag [i-1] [ v - w [i] ] + val [i]。
②不裝入第i件物品
那麼價值就是處理i-1件物品時計算出來的值,不變。
二者取最大值即可。
#include int max(int a,int b)``
int bag[1000][1000];//儲存解的陣列
int w[1000],val[1000];//每件物品的大小與價值
int main()
通過1.3的**可以很容易的看出,當物品有1,000件,揹包大小為1,000時,我們就需要開乙個1,000,000大小的陣列了,要是處理的資料再稍微大一點,就會導致陣列開的過大,然後記憶體溢位。
所以為了解決更大的資料,空間的優化是必要的。
我們可以發現,當我們處理第i件物品時,要用到的只是處理第i-1件物品時的資料,再之前的就用不到了。
所以,我們可以每次處理物品時,就把資料進行一次覆蓋,這樣二維陣列就能降維到一維了。
但需要注意!降維到一維陣列後,我們處理第i件物品時,就不能從大小為1的揹包一直順序處理到大小為m的揹包了。為什麼?因為這樣的話,處理i-1件物品時的資料會在本次處理中被覆蓋,而處理更大的揹包時是會用到小揹包的資料的。
這樣就會出現——已經塞了第i件物品了,處理時就當做沒塞,就會wa了。
所以我們這裡進行倒序處理,因為處理小揹包用不到大揹包的資料,覆蓋了也就覆蓋了,無所謂。
#include
intmax
(int a,
int b)
int bag[
1000];
//降維到一維的陣列
int w[
1000
],val[
1000];
//每件物品的大小與價值
intmain()
優化完後,空間複雜度就從o(t*n)縮小到了o(n),大大節省了記憶體,也就可以處理更大的資料了。
有m株藥草,每株藥草有其對應的價值及採摘該藥草要花費的時間,在n時間內,求採摘的藥草的最大價值。這其實就是換了個題幹的0/1揹包模板題,上面的**直接複製貼上就可ac。
你有n元錢,有m種物品,每種一件,每件物品都有對應的**,並且你對每件物品都賦予了乙個重要度(從1~5),求購買的物品的最高價效比和。依然是換了個題幹的0/1揹包模板,只要把價值的計算變成物品***重要度即可(val[i] = w[i] * rank [i] )。注:價效比=物品***重要度。
有乙個容量為v的箱子,和n個物品,每個物品的體積為整數,裝任意個物品,問剩餘的最小體積是多少?本題中,物品的價值與消費相同,也就是w[i]==val[i],代換進原來的**即可。
注意最後輸出的是剩餘的最小體積,故應當輸出v-bag[v]。
你有n元錢,有m種菜,每種只有乙份,且有對應的**。要求你把所有的錢都花光,問有多少種不同的點菜方案?如果只有0元錢,那只有一種點菜方式——啥都不點。
接下來的遞推公式為bag[money]+=bag[money - w[i] ]。
即花n元的點菜方式 = 花(n-某道菜**)元錢的點菜方式的和。
揹包 01揹包
01揹包 有n種物品與承重為m的揹包。每種物品只有一件,每個物品都有對應的重量weight i 與價值value i 求解如何裝包使得價值最大。dp i,v 表示前i個物體 包括第i個 面對容量為v的揹包的最大價值,c i 代表物體i的重量,w i 代表物體i的價值 如果第i個物體不放入揹包,則揹包...
揹包專題 01揹包
暑假集訓開始了,按照隊裡的分配,我是弄dp的,嘛,於是我又一次的開始了從01揹包開始學習,昨天將杭電的幾道01揹包重新做了一遍,下面講講我自己對於01揹包的理解。首先01揹包題目的雛形是 有n件物品和乙個容量為v的揹包。第i件物品的費用是c i 價值是w i 求解將哪些物品裝入揹包可使價值總和最大。...
01揹包,完全揹包
動態規劃 動態規劃的核心是狀態以及狀態轉移方程。需要定義乙個 i,j 狀態以及該狀態的指標函式d i,j 01揹包 有n種物品,每種只有乙個,第i件物品的體積為vi質量為wi。選一些物品裝到體積為c的揹包中,使其體積不超過c的前提下重量最大。namevw abcd e 子問題定義 dp i j 表示...