题目地址:
https://www.acwing.com/problem/content/4/
有 N N N种物品和一个容量是 V V V的背包。第 i i i种物品最多有 s i s_i si件,每件体积是 v i v_i vi,价值是 w i w_i wi。求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。输出最大价值。
输入格式:
第一行两个整数,
N
N
N,
V
V
V,用空格隔开,分别表示物品种数和背包容积。接下来有
N
N
N行,每行三个整数
v
i
,
w
i
,
s
i
v_i,w_i,s_i
vi,wi,si,用空格隔开,分别表示第
i
i
i种物品的体积、价值和数量。
输出格式:
输出一个整数,表示最大价值。
数据范围:
0
<
N
,
V
≤
100
0< N, V\le 100
0<N,V≤100
0
<
v
i
,
w
i
,
s
i
≤
100
0<v_i,w_i,s_i\le 100
0<vi,wi,si≤100
思路是动态规划。设 f [ i ] [ j ] f[i][j] f[i][j]是如果只取前 i i i件物品,并且总重量不超过 j j j的情况下能达到的最大价值。那么所有方案可以按照第 i i i件物品取多少个来分类。显然最少可以取 0 0 0个,最多可以取 min { s i , j / v i } \min\{s_i,j/v_i\} min{si,j/vi}个,所以有 f [ i ] [ j ] = max k = 0 , 1 , . . . , min { s i , j / v i } { f [ i − 1 ] [ j − k v i ] + k w i } f[i][j]=\max_{k=0,1,...,\min\{s_i,j/v_i\}}\{f[i-1][j-kv_i]+kw_i\} f[i][j]=k=0,1,...,min{si,j/vi}max{f[i−1][j−kvi]+kwi}最后返回 f [ N ] [ V ] f[N][V] f[N][V]即可(此题还有一种二进制优化,参考https://blog.csdn.net/qq_46105170/article/details/113840962)。代码如下:
#include <iostream>
using namespace std;
const int N = 110;
int n, m;
int f[N][N];
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
int v, w, s;
scanf("%d%d%d", &v, &w, &s);
for (int j = 0; j <= m; j++)
for (int k = 0; k <= s && k * v <= j; k++)
f[i][j] = max(f[i][j], f[i - 1][j - k * v] + k * w);
}
printf("%d\n", f[n][m]);
}
时空复杂度 O ( N V max i s i ) O(NV\max_i s_i) O(NVmaxisi),空间 O ( N V ) O(NV) O(NV)。