【ACWing】2. 01揹包問題
阿新 • • 發佈:2021-02-06
題目地址:
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,V≤1000
v
i
,
w
i
≤
1000
v_i,w_i\le 1000
vi,wi≤1000
思路是動態規劃。設
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[i−1][j],f[i−1][j−vi]+wi}注意,能取當且僅當
j
≥
v
i
j\ge v_i
j≥vi。可以考慮空間優化,我們注意到更新
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)。