题目地址:
https://www.acwing.com/problem/content/8/
有 N N N件物品和一个容量是 V V V的背包,背包能承受的最大重量是 M M M。每件物品只能用一次。体积是 v i v_i vi,重量是 m i m_i mi,价值是 w i w_i wi。求解将哪些物品装入背包,可使物品总体积不超过背包容量,总重量不超过背包可承受的最大重量,且价值总和最大。输出最大价值。
输入格式:
第一行两个整数,
N
,
V
,
M
N,V,M
N,V,M,用空格隔开,分别表示物品件数、背包容积和背包可承受的最大重量。接下来有
N
N
N行,每行三个整数
v
i
,
m
i
,
w
i
v_i,m_i,w_i
vi,mi,wi,用空格隔开,分别表示第
i
i
i件物品的体积、重量和价值。
输出格式:
输出一个整数,表示最大价值。
数据范围:
0
<
N
≤
1000
0<N≤1000
0<N≤1000
0
<
V
,
M
≤
100
0<V,M≤100
0<V,M≤100
0
<
v
i
,
m
i
≤
100
0<v_i,m_i≤100
0<vi,mi≤100
0
<
w
i
≤
1000
0<w_i≤1000
0<wi≤1000
思路是动态规划。设 f [ i ] [ j ] [ k ] f[i][j][k] f[i][j][k]是在只考虑前 i i i个物品的情况下,体积不超过 j j j并且重量不超过 k k k的方案里物品总价值最大值。那么可以按照第 i i i个物品选还是不选来分类。则有: f [ i ] [ j ] [ k ] = max { f [ i − 1 ] [ j ] [ k ] , f [ i − 1 ] [ j − v i ] [ k − m i ] + w i } f[i][j][k]=\max\{f[i-1][j][k],f[i-1][j-v_i][k-m_i]+w_i\} f[i][j][k]=max{f[i−1][j][k],f[i−1][j−vi][k−mi]+wi}可以把空间优化为两维,类似 0 − 1 0-1 0−1背包的做法,除了最外层循环之外,其余循环从大到小遍历。代码如下:
#include <iostream>
using namespace std;
const int S = 110;
int n, V, M;
int f[S][S];
int main() {
scanf("%d%d%d", &n, &V, &M);
for (int i = 1; i <= n; i++) {
int v, m, w;
scanf("%d%d%d", &v, &m, &w);
for (int j = V; j >= 0; j--)
for (int k = M; k >= 0; k--)
if (j >= v && k >= m) f[j][k] = max(f[j][k], f[j - v][k - m] + w);
}
printf("%d\n", f[V][M]);
}
时间复杂度一样,空间 O ( V M ) O(VM) O(VM)。