参考链接:blog.csdn.net/lanyu_01/ar…
问题描述:
一个背包的总容量为V,现在有n类物品,第i类物品的重量为weight[i],价值为value[i],那么往背包里装物品,使得包内的物品总价值最大。主要有三种装法:
- 0-1背包:每类物品最多只能装一次;
- 完全背包:物品无限量;
- 多重背包:每类物品有个数限制,第i类物品有num[i]个;
1,0-1背包
- 使用动态规划求解,初始化dp[n+1][v+1],dp[i][j]代表前i件物品使用j容量的背包的物品最大价值;这样我们求dp[n][v]就是我们想要的结果;
package woek1;
import java.util.Scanner;
public class pack0_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int v =sc.nextInt();
int[] weight = new int[n];
int[] value = new int[n];
for(int i = 0;i<n;i++) {
weight[i] = sc.nextInt();
value[i] = sc.nextInt();
}
int[][] dp = new int[n+1][v+1];
for(int i = 1;i<=n;i++)
for(int j = 1;j<v+1;j++) {
//背包容量大于当前物品重量时;选择是否选择此物品放入背包
//注意下标是从1开始的,当前应该-1;
if(j>=weight[i-1]){
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-weight[i-1]]+value[i-1]);
} else {
//不然直接不放入背包
dp[i][j] = dp[i-1][j];
}
}
System.out.println(dp[n][v]);
}
}
0-1背包优化
使用一维数组dp[v+1],dp[i]代表容量为i所能装入物品的最大价值
package woek1;
import java.util.Scanner;
public class pack0_1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int v =sc.nextInt();
int[] weight = new int[n];
int[] value = new int[n];
for(int i = 0;i<n;i++) {
weight[i] = sc.nextInt();
value[i] = sc.nextInt();
}
int[] dp = new int[v+1];
for(int i = 1;i<=n;i++)
//注意下标问题;
for(int j = v;j>=weight[i-1];j--) {
dp[j] = Math.max(dp[j], dp[j-weight[i-1]]+value[i-1]);
}
System.out.println(dp[v]);
}
}
完全背包
和0-1背包基本类似,但状态方程变为dp[i][j] = Math.max(dp[i-1][j],dp[i][j-weight[i]]+value[i];
package woek1;
import java.util.Scanner;
public class completePack {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int v =sc.nextInt();
int[] weight = new int[n];
int[] value = new int[n];
for(int i = 0;i<n;i++) {
weight[i] = sc.nextInt();
value[i] = sc.nextInt();
}
int[][] dp = new int[n+1][v+1];
for(int i = 1;i<=n;i++)
for(int j = 1;j<=v;j++) {
if(j>=weight[i-1])
dp[i][j] = Math.max(dp[i-1][j], dp[i][j-weight[i-1]]+value[i-1]);
else
dp[i][j] = dp[i-1][j];
}
System.out.println(dp[n][v]);
}
}
多重背包
和0-1背包类似,只不过多个数量限制,现在加一个循环,对数量合适的,选出最大的物品价值;
package woek1;
import java.util.Scanner;
public class completePack {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int v =sc.nextInt();
int[] weight = new int[n];
int[] value = new int[n];
int[] num = new int[n];
for(int i = 0;i<n;i++) {
weight[i] = sc.nextInt();
value[i] = sc.nextInt();
num[i] = sc.nextInt();
}
int[][] dp = new int[n+1][v+1];
for(int i = 1;i<=n;i++)
for(int j =1;j<=v;j++) {
if(weight[i-1] > j)
dp[i][j] = dp[i-1][j];
else {
//求出符合条件的该物品数量最大值,进行循环求解
int maxV = Math.min(num[i-1], j/weight[i-1]);
for(int k = 0;k<=maxV;k++) {
dp[i][j] = Math.max(dp[i-1][j], dp[i-1][j-k*weight[i-1]]+k*value[i-1]);
}
}
}
System.out.println(dp[n][v]);
}
}