多重背包问题相比01背包,限定了物品件数,求容量一定的情况下,价值最大
多重背包代码
import java.util.Scanner;
public class Main1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while ( sc.hasNextInt() ) {
int num = sc.nextInt();//总物品种类
int money = sc.nextInt();//总钱数,也就是容量V
int[] price = new int[num + 1];//价格,也就是权重wei
int[] manyidu = new int[num + 1];//满意度,也就是价值val
int[] cnt = new int[num + 1];//每个物品的个数cnt
for (int i = 1; i <= num; i++) {
price[i] = sc.nextInt();
manyidu[i] = sc.nextInt();
cnt[i] = sc.nextInt();
}
int maxManyidu = getMax(price, manyidu, cnt, num, money);
System.out.println(maxManyidu);
}
}
private static int getMax(int[] price, int[] manyidu, int[] cnt, int num, int money) {
int[] V = new int[money + 1];//初始化价值的数组
int cntNum = 0;//初始化所有种类的个数
for (int i = 1; i <= num; i++) {//计算所有种类的数量,目的是转换为01背包问题
cntNum += cnt[i];
}
int cur = 1;//标记进行到哪个物品了
int sumCount = 0;//初始化当前进行到哪个位置的总和
for (int i = 1; i <= cntNum; i++) {//循环所有物品的个数,也就是转换为01背包
int oneMax = sumCount + cnt[cur];//按物品种类进行循环
if (i > oneMax) {//判断当前是不是计算完当前物品的数量
sumCount += cnt[cur];//每计算完当前的种类,那么就加上已经计算完的物品个数
cur++;//移动到下一个物品
}
// 转换为01背包,从大到小开始递减
for (int j = money; j >= price[cur]; j--) {//只有在当前钱数或者容量大于这个物品价值的时候进行迭代
/**
* 当前这个位置所对应的最大价值V[j],
* 当前位置的大小和当前的钱数-当前一个物品的价格所对应的最大价值,
* 再加上当前物品的价值,也就是当前物品花费所能提供的价值,V[j - price[cur]] + manyidu[cur]
* 比较这两个的最大值
*/
V[j] = Math.max(V[j], V[j - price[cur]] + manyidu[cur]);
}
}
return V[money];
}
}
测试案例
//3 100,表示3个种类的物品,总钱数为100
//26 100 4,依次表示为每件物品价格,价值,数量
//5 1 4
//5 2 2
//输出306
//3 21
//4 2 7
//9 11 2
//6 3 5
//22
//输出22
01背包问题
有n 种不同的物品,每个物品有两个属性,size 体积,value 价值,现在给一个容量为 w 的背包,问最多可带走多少价值的物品。也就是多重背包的个数限制为1.
import java.util.Scanner;
public class Bag01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
while ( sc.hasNextInt() ) {
int n = sc.nextInt();//总物品种类
int cp = sc.nextInt();//总容量cp
int[] wei = new int[n + 1];//权重wei
int[] val = new int[n + 1];//价值val
for (int i = 1; i <= n; i++) {
wei[i] = sc.nextInt();
val[i] = sc.nextInt();
}
int maxVal = getMax01(cp, wei, val, n);
System.out.println(maxVal);
}
}
private static int getMax01(int cp, int[] wei, int[] val, int n) {
int[] V = new int[cp + 1];
for (int i = 1; i <= n; i++) {
for (int j = cp; j >= wei[i]; j--) {
V[j] = Math.max(V[j], V[j - wei[i]] + val[i]);
}
}
return V[cp];
}
}
测试代码
//4 8,物品个数,总容量
//2 3依次为权重,价值
//3 4
//4 5
//5 6
//10输出结果
完全背包相对于01背包和多重背包不限定数量,所以就是尽可能的装满。
而完全背包只需将第二层的循环变换一下即可
for (int i = 1; i <= n; i++) {
for (int j = wei[i]; j <= cp; j++) {
V[j] = Math.max(V[j], V[j - wei[i]] + val[i]);
}
}
这篇文章写得很详细,可以直接看这一篇https://blog.csdn.net/yandaoqiusheng/article/details/84782655