有n件物品和乙個容量為v的揹包,求可以得到的最大價值。其中重量是w[i],價值是v[i]。
例 4 5
1 22 3
3 42 2
01揹包問題的常用的f[v]=max(f[v],f[v-w[i]]+v[i])的解法是由樹遞迴得來的,這裡從頭推演一遍。
我們可以這樣理解,從第乙個物品開始,每個物品都有兩種情況:選或不選,於是就有下圖:
從此我們可以設函式res(int i,int j)(i表示第幾個物品,j表示揹包剩餘容量),不斷的判斷選還是不選,不斷地遞迴呼叫,直到i=n+1時,就開始回溯,逐層返回得到的最大價值,最終獲得揹包能裝下的最大價值。
由此我們可以寫出遞迴求解的**:
#include#include#include#includeusing namespace std;
const int maxn=101;
int w[maxn],v[maxn],n,w1;
int res(int i,int j)
int main()
int main()
{ memset(dp,-1,sizeof(dp));
scanf("%d%d",&n,&w1);
for(int i=0;i我們由此又可以得出打表的方法即:
for i = 1.......n
for j =1....v
dp[i][j]=max(dp[i-1][ j ] ,dp[ i-1 ][ j-w[ i ] ] + v[ i ]);
再對空間複雜度進行優化可得:
for i = 1.......n
for j =v....p[i]
dp[ j ]= max( dp[ j ] ,dp[ j-w[ i ] ] + v[ i ]);
因此就得到了我們現在常用的計算01揹包的方法。
01揹包 例題:不需要恰好裝滿)
我們還應該注意初始化的細節問題:
我們看到的求最優解的揹包問題題目中,事實上有兩種不太相同的問法。 有的題目要求「恰好裝滿揹包」時的最優解,有的題目則並沒有要求必須把背 包裝滿。一種區別這兩種問法的實現方法是在初始化的時候有所不同。 如果是第一種問法,要求恰好裝滿揹包,那麼在初始化時除了f[0]為0,其 它f[1..v ]均設為−∞,這樣就可以保證最終得到的f[v ]是一種恰好裝滿揹包的 最優解。 如果並沒有要求必須把揹包裝滿,而是只希望**盡量大,初始化時應該 將f[0..v ]全部設為0。
這是為什麼呢?可以這樣理解:初始化的f陣列事實上就是在沒有任何物 品可以放入揹包時的合法狀態。如果要求揹包恰好裝滿,那麼此時只有容量 為0的揹包可以在什麼也不裝且價值為0的情況下被「恰好裝滿」,其它容量的 揹包均沒有合法的解,屬於未定義的狀態,應該被賦值為-∞了(即控制在揹包沒有裝滿時是不合法的)。如果揹包並非 必須被裝滿,那麼任何容量的揹包都有乙個合法解「什麼都不裝」,這個解的 價值為0,所以初始時狀態的值也就全部為0了(在揹包沒有被裝滿也是合法的)。
揹包01問題初理解
揹包問題 knapsack problem 是一種組合優化的np完全問題。問題可以描述為 給定一組物品,每種物品都有自己的重量和 在限定的總重量內,我們如何選擇,才能使得物品的總 最高。問題的名稱 於如何選擇最合適的物品放置於給定揹包中。具體理解可以直接通過下面的例子來理解揹包問題 揹包問題的乙個例...
01揹包問題的理解
01揹包是 n個物品重量和價值分別為w i v i 揹包可以容納的重量為weight,怎麼裝下最大價值的物品?狀態轉移方程是 value i,w max value i 1,w w i v i value i 1,w 要求w的解,那麼先求w w i 的解,w w i 的值只有在知道了i是多少時才知道...
揹包問題 01揹包問題
n個物品,總體積是v,每個物品的體積的vi,每個物品的最大價值是wi,在不超過v的體積下求最大價值 eg揹包容積為 5 物品數量為 4 物品的體積分別為 物品的價值分別為 思路定義乙個二位陣列int f new int n 1 v 1 f i j 就表示在1 i個物品中選取體積小於v的情況的最大價值...