1. 程式人生 > 其它 >【ACWing】2. 01揹包問題

【ACWing】2. 01揹包問題

技術標籤:AC 貪心、動態規劃與記憶化搜尋動態規劃演算法

題目地址:

https://www.acwing.com/problem/content/2/

N N N件物品和一個容量是 V V V的揹包。每件物品只能使用一次。第 i i i件物品的體積是 v i v_i vi,價值是 w i w_i wi。要求將物品裝入揹包,可使這些物品的總體積不超過揹包容量,且總價值最大。輸出最大價值。

資料範圍:
N , V ≤ 1000 N,V\le 1000 N,V1000
v i , w i ≤ 1000 v_i,w_i\le 1000 vi,wi1000

思路是動態規劃。設 f [ i ] [ j ] f[i][j]

f[i][j]是從前 i i i件物品中取,總體積不超過 j j j的情況下的最大價值。那麼可以按照第 i i i件物品取還是不取,來分類。則有: f [ i ] [ j ] = max ⁡ { f [ i − 1 ] [ j ] , f [ i − 1 ] [ j − v i ] + w i } f[i][j]=\max\{f[i-1][j],f[i-1][j-v_i]+w_i\} f[i][j]=max{f[i1][j],f[i1][jvi]+wi}注意,能取當且僅當 j ≥ v i j\ge v_i jvi。可以考慮空間優化,我們注意到更新 f f f的時候,只會用到其上方和上方左邊的數,所以可以只開一行陣列,然後每次從大到小更新。程式碼如下:

#include <iostream>
using namespace std;

const int N = 1010, V = 1010;
int v[N], w[N];
int f[V];

int main() {
	// n是總個數,m是總體積
    int n, m;
    cin >> n >> m;

    for (int i = 1; i <= n; i++)
        cin >> v[i] >> w[i];

    for (int i = 1; i <= n; i++) 
        for
(int j = m; j >= 1; j--) { if (j >= v[i]) f[j] = max(f[j], f[j - v[i]] + w[i]); } cout << f[m] << endl; return 0; }

時間複雜度 O ( m n ) O(mn) O(mn),空間 O ( m ) O(m) O(m)