有 N {N} N 件物品和一个容量是 V V V 的背包。每件物品只能使用一次。
第 i i i 件物品的体积是 v i v_i vi,价值是 w i w_i wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数, N , V N,V N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N N N行,每行两个整数 v i v_i vi, w i w_i wi,用空格隔开,分别表示第 i i i 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0 < N , V ≤ 1000 0
0 < v i , w i ≤ 1000 0
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例
8
定义记录状态的函数 f [ i ] [ j ] f[i][j] f[i][j],意为:当背包容量为 j j j时,选取前 i i i个物品能获取的最大价值为 f [ i ] [ j ] f[i][j] f[i][j]。
对 f [ i ] [ j ] f[i][j] f[i][j]而言,有2种方式可从前一阶段到达 f [ i ] [ j ] f[i][j] f[i][j]:1.将物品 i i i不纳入背包 f [ i ] [ j ] = f [ i − 1 ] [ j ] f[i][j]=f[i-1][j] f[i][j]=f[i−1][j]
2.物品 i i i纳入背包 f [ i ] [ j ] = f [ i − 1 ] [ j − v [ i ] ] + w [ i ] f[i][j]=f[i-1][j-v[i]]+w[i] f[i][j]=f[i−1][j−v[i]]+w[i]//如果纳入背把,则需预留 v [ i ] v[i] v[i]空位,因此剩下 j − v [ i ] j-v[i] j−v[i]的空位
代码
#include
using namespace std;
const int N = 1010;
int f[N][N];
int v[N], w[N];
int n, m;
int main(){
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=1;j<=m;j++){
f[i][j]=f[i-1][j];
if (j >= v[i]) f[i][j] = max(f[i][j], f[i - 1][j - v[i]] + w[i]);
}
}
cout<
从以上基本思路得知,后一状态的 f f f仅与前一状态的有关,因此可优化为一维数组。
若 j j j从 v [ i ] v[i] v[i]遍历到 m m m,则 f [ j − v [ i ] ] f[j - v[i]] f[j−v[i]]可能取到的是 i i i层状态下的值,而并非 i − 1 i-1 i−1层的,为避免这一情况,需将 j j j从后往前遍历。
#include
using namespace std;
const int N = 1010;
int f[N];
int v[N], w[N];
int n, m;
int main(){
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>=v[i];j--){
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
cout<
有 N {N} N 件物品和一个容量是 V V V 的背包。每种物品都有无限件可用。
第 i i i 件物品的体积是 v i v_i vi,价值是 w i w_i wi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。
输入格式
第一行两个整数, N , V N,V N,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 N N N行,每行两个整数 v i v_i vi, w i w_i wi,用空格隔开,分别表示第 i i i 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0 < N , V ≤ 1000 0
0 < v i , w i ≤ 1000 0
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例
10
与01背包问题相似,不过需遍历物品 i i i取 1 , 2 , 3... k , 且 取 到 k 时 不 超 过 背 包 容 量 上 限 1,2,3...k,且取到k时不超过背包容量上限 1,2,3...k,且取到k时不超过背包容量上限
代码
#include
using namespace std;
const int N = 1010;
int f[N][N];
int v[N], w[N];
int n, m;
int main(){
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=1;j<=m;j++){
for(int k=0;v[i]*k<=j;k++){
f[i][j] = max(f[i][j], f[i-1][j - k*v[i]] + k*w[i]);
}
}
}
cout<
代码
#include
using namespace std;
const int N = 1010;
int f[N];
int v[N], w[N];
int n, m;
int main(){
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=v[i];j<=m;j++){
f[j] = max(f[j], f[j - v[i]] + w[i]);
}
}
cout<