01揹包問題

2021-09-17 01:22:17 字數 2218 閱讀 9711

有$n$件物品和乙個容量為$v$的揹包。第$i$件物品的體積是$c_i$,其價值是$w_i$。求解,在不超過揹包容量情況下,將哪些物品裝入揹包可使價值總和最大。

這是最基礎的揹包問題,特點是:每種物品僅有一件。

狀態$f[i,v]$表示前$i$件物品中選擇若干件放在容量為$v$的揹包中,可以取得的最大價值。

轉移方程

$$f[i,v]=\max

$$對於第$i$件物品,有放與不放兩種選擇。若選擇不放,$f[i,v]=f[i−1,v]$;若選擇放,$v−c_i$確保有足夠的空間,隨之$f[i,v]=f[i−1,v−c_i]+w_i$。

/**

* * author 劉毅(limer)

* date 2017-03-17

* mode c++

*/#include#includeusing namespace std;

int main()

; //第i個物品的體積(下標從1開始)

int w[n + 1] = ; //第i個物品的價值

int f[n + 1][v + 1] = ; //狀態

for (int i = 1; i <= n; i++) //對於第i個物品

for (int v = 0; v <= v; v++)

cout << "最大價值是:" << f[n][v] << endl; //9

return 0;

}

以上方法的時間和空間複雜度均為$o(vn)$,其中時間複雜度應該已經不能再優化了,但空間複雜度卻可以優化到$o(v)$。

先考慮上面講的基本思路如何實現,肯定是有乙個主迴圈i ← 1 to n,每次算出來二維陣列$f[i,v]$的所有值。那麼,如果只用乙個陣列$f[v]$能不能保證第$i$次迴圈結束後$f[v]$中表示的就是我們定義的狀態$f[i,v]$呢?

$f[i,v]$是由$f[i−1,v]$和$f[i−1,v−c_i]$兩個子問題遞推而來,能否保證在推$f[i,v]$時(也即在第$i$次主迴圈中推$f[v]$時)能夠取用$f[i−1,v]$和$f[i−1,v−c_i]$的值呢?

事實上,這要求在每次主迴圈中我們以v ← v to c[i]的遞減順序計算$f[v]$,這樣才能保證計算$f[v]$時$f[v−c_i]$儲存的是狀態$f[i−1,v−c_i]$的值。

優化後的**如下:

/**

* * author 劉毅(limer)

* date 2017-03-17

* mode c++

*/#include#includeusing namespace std;

int main()

; //第i個物品的體積(下標從1開始)

int w[n + 1] = ; //第i個物品的價值

int f[v + 1] = ; //狀態

for (int i = 1; i <= n; i++) //對於第i個物品

for (int v = v; v >= c[i]; v--)

f[v] = max(f[v], f[v - c[i]] + w[i]);

cout << "最大價值是:" << f[v] << endl; //9

return 0;

}

我們看到的求最優解的揹包問題題目中,事實上有兩種不太相同的問法。有的題目要求「恰好裝滿揹包」時的最優解,有的題目則並沒有要求必須把揹包裝滿。這兩種問法的實現方法只是在初始化的時候有所不同。

如果是第一種問法,要求恰好裝滿揹包,那麼在初始化時除了f[0]為0,其它f[1]...f[v]均設為−∞,這樣就可以保證最終得到的f[v]是一種恰好裝滿揹包的最優解。如果並沒有要求必須把揹包裝滿,而是只希望**盡量大,初始化時應該將f[0]...f[v]全部設為0。

這是為什麼呢?可以這樣理解:初始化的f陣列事實上就是在沒有任何物品可以放入揹包時的合法狀態。如果要求揹包恰好裝滿,那麼此時只有容量為0的揹包可以在什麼也不裝且價值為0的情況下被「恰好裝滿」,其它容量的揹包均沒有合法的解,屬於未定義的狀態,應該被賦值為-∞了。如果揹包並非必須被裝滿,那麼任何容量的揹包都有乙個合法解「什麼都不裝」,這個解的價值為0,所以初始時狀態的值也就全部為0了。

[ 1 ] .揹包九講.

文章**我的個人部落格:

揹包問題 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...