背包九讲
01背包
有 NN 件物品和一个容量是 VV 的背包。每件物品只能使用一次。
第 ii 件物品的体积是 vivi,价值是 wiwi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。输入格式
第一行两个整数,N,VN,V,用空格隔开,分别表示物品数量和背包容积。
接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 件物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<vi,wi≤1000输入样例
4 5 1 2 2 4 3 4 4 5
输出样例:
8
二维数组
import java.util.*;
public class Main {
// f[i][j]
// 1.不选第i个物品 f[i][j]=f[i-1][j]
// 2.选第i个物品 f[i][j]=f[i-1][j-v[i]]
// f[0][0]=0;
// f[i][j]=max(1,2);
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
int N=1010;
int f[][]=new int[N][N];//前i个物品体积为j的时候的最大价值
int v[]=new int[N];//体积
int w[]=new int[N];//价值
int n=in.nextInt();//数量
int m=in.nextInt();//体积
for(int i=1;i<=n;i++){
v[i]=in.nextInt();
w[i]=in.nextInt();
}
for(int i=1;i<=n;i++){
for(int j=0;j<=m;j++){
f[i][j]=f[i-1][j];//不选第i个物品
if(j>=v[i])//选第i个物品
f[i][j]=Math.max(f[i][j],f[i-1][j-v[i]]+w[i]);
}
}
System.out.println(f[n][m]);
}
}
一维数组
import java.util.*;
public class Main {
static final int N=1010;
public static void main(String args[]){
Scanner in=new Scanner(System.in);
int n=in.nextInt();
int m=in.nextInt();
int v[]=new int[N];
int w[]=new int[N];
int dp[]=new int[N];
for(int i=1;i<=n;i++){
v[i]=in.nextInt();
w[i]=in.nextInt();
}
/*将二维数组压缩成一维数组不断更新
dp[j]从最大容量开始更新,否则会将上一次循环的给更新掉
j前边的部分就是二维数组前i-1个的结果
所以从后边开始更新就不会影响结果
如果使用顺序,会先更新f[4],再更新f[7],对于这个书包问题来讲,
就是有可能,在更新f[4]的时候,已经把这次能加的物品加进来了,
然后更新f[7]的时候,还有可能再加一次,所以必须使用逆序,
保证,f[4]是没有加入新物品前,背包里的最优解。
*/
for(int i=1;i<=n;i++){
for(int j=m;j>=v[i];j--){
// if(j>=v[i])可以优化到循环内部
dp[j]=Math.max(dp[j],dp[j-v[i]]+w[i]);
}
}
System.out.println(dp[m]);
}
}
初始化情况
f[0] 的初始值是0 其余都是负无穷(正好装满的时候最大值)
除0外初始化为负无穷,那么仅刚好装下的位置是正数(从0加),其余位置为负数(从负无穷加)
求恰好装满的最大价值,需要枚举一遍。
f[] 的初始值都是0(<=m时的最大值)
完全背包问题
有 NN 种物品和一个容量是 VV 的背包,每种物品都有无限件可用。
第 ii 种物品的体积是 vivi,价值是 wiwi。
求解将哪些物品装入背包,可使这些物品的总体积不超过背包容量,且总价值最大。
输出最大价值。输入格式
第一行两个整数,N,VN,V,用空格隔开,分别表示物品种数和背包容积。
接下来有 NN 行,每行两个整数 vi,wivi,wi,用空格隔开,分别表示第 ii 种物品的体积和价值。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N,V≤10000<N,V≤1000
0<vi,wi≤10000<vi,wi≤1000输入样例
4 5 1 2 2 4 3 4 4 5
输出样例:
10
完全背包和01背包的唯一区别就是一个物品可以用无限次
初始化跟01背包一样
import java.util.*;
public class Main{