有 N 种物品和一个容量是 V的背包,每种物品都有无限件可用。第 i 种物品的体积是 vi,价值是 wi。求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。输出最大价值。
输入格式
第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。接下来有 N
行,每行两个整数 vi,wi,用空格隔开,分别表示第 i种物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤1000
0<vi,wi≤1000
输入样例
4 5
1 2
2 4
3 4
4 5
输出样例: 10
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define N 1001
int main(){
int n,m; // N件物品,V 是总容量
scanf("%d %d\n",&n,&m);
int v[N],w[N];
int f[N] = {0};
for(int i =1; i <= n ; i++){
scanf("%d %d\n",&v[i],&w[i]);
}
for(int i =1; i <= n; i++){
for(int j = 0; j <= m; j++){
/* f[j] = f[j-1]; 这句话放在01背包中是正确的,在完全背包中
f[j] = f[j-1]; 加上这句将导致错误,因为虽然容积增加了一无法容纳新的元素
但是可能使原来已有的元素能够重复一次,比如新元素重量为5,背包容量加一不能容纳新的元素,但是如果以前出现的输入中
有重量为1的物品,那个f[j]的价值可能比f[j-1]要大,
且完全背包问题只可以正序,因为可以取无数次,而01背包则只能逆序(只针对一维)
*/
if(j >= v[i]){
f[j] = fmax(f[j],f[j-v[i]]+w[i]);
}
}
}
int res = f[m];
printf("%d",res);
return 0;
}
/*
// 二维解法
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define N 1001
int main(){
int n,m; // N件物品,V 是总容量
scanf("%d %d\n",&n,&m);
int v[N],w[N];
int f[N][N] = {0};
for(int i =1; i <= n ; i++){
scanf("%d %d\n",&v[i],&w[i]);
}
for(int i =1; i <= n; i++){
for(int j = 0; j <= m ; j++){
f[i][j] = f[i-1][j]; /*当重量不足以容纳新的元素,则最大值就是保持容量J的
情况下前i-1 个的最大值;
if(j >= v[i])
{
f[i][j] = fmax(f[i][j],f[i][j-v[i]]+w[i]);
}
}
}
int res = f[n][m];
printf("%d",res);
return 0;
}
*/
完全背包问题和01背包本质是一类问题,在01背包中在处理背包容量的循环中,考虑到每种物品只能用一次因此必须采用逆序操作,但是在完全背包中,这种问题就恰恰相反,考虑到一种物品可以多次使用因此必须采用正序操作,对于正序和逆序不是很了解的话可以参考下面的链接,里面有文字解释 同时附带了相关的视频链接
01背包的讲解