多重背包
多重背包是介于01背包和完全背包之间:
有容积为V的背包,我们给定一些物品,每种物品包含体积w,价值v和数量k,
求用该背包能装下的最大价值总量。
与之前的背包问题都不同,每种物品可选数量不再为无穷多或者1,而是介于其中的一个确定数k
我们可以将多重背包问题转化到01背包上去,即每种物品均被视为k种不同的物品,不过这样时间复杂度较高
我们可以选择有技巧的拆分。将原数量为k的物品分成若干组,魅族物品看成一件物品,其价值和重量为该组中
所有的价值的总和
每组物品包含的原物品个数分别为 1、2、4、…k-2^c+1,其中c为使k-2^c大于0的最大整数。
这种类似二进制的拆分,不仅将物品数量大大降低,同时通过对这些若干个原物品组合得到的新物品的不同组合,
可以得到0到k之间任意件物品的价值重量和,对这些新的物品做01背包,即可得到多重背包问题的解。
珍惜现在,感恩生活(九度103题)
单输入输出版
题目描述:
为了挽救灾区同胞的生命,心系灾区的你准备自己采购一些粮食支援灾区,现假设你一共有资金n元,
而市场有m种大米,每种大米都是袋装产品,其价格不等,并且只能整袋采购。请问你用有限的资金最多
采购多少大米呢?
输入:
第一行两个整数n和m(1 <= n <= 100,1<=m <=100),分别表示经费的金额和大米的种类,
然后m行数据,每行包括三个数w,v,k(1 <= w <= 20,1<= v <=200 ,1<=k <=20)
分别对应每袋的价格,每袋的重量,对应大米袋数
输出:
请输出能购买大米的最大重量,可以假设经费买不光所有大米,并且经费可以不用完。
转化为01背包问题
public class Main {
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
int s=input.nextInt();
int n=input.nextInt();
int W[]=new int[100001];
int V[]=new int[100001];
int dp[]=new int[100001];
int w_index=0;
int v_index=0;
for (int i = 1; i <= n; i++) {
int w=input.nextInt();
int v=input.nextInt();
int k=input.nextInt();
for (int j = 0; j <k; j++) {
W[w_index]=w;
V[v_index]=v;
w_index++;
v_index++;
}
}
for (int i = 0; i < W.length; i++) {
for (int j = s; j >= W[i]; j--) {
dp[j]=Math.max(dp[j], dp[j-W[i]]+V[i]);
}
}
System.out.println(dp[s]);
}
}
public class 多重背包问题优化解 {
static int W[] = new int[2001];
static int V[] = new int[2001];
static int num[] = new int[2001];
static int dp[] = new int[2001];
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int n = input.nextInt();
int m = input.nextInt();
int cnt = 0;// 拆分后的物品总数
for (int i = 1; i <= m; i++) {
int w = input.nextInt();
int v = input.nextInt();
int k = input.nextInt();
int c = 1;
while (k - c > 0) {// 对输出的数字k,拆分成1,2,4...k-2^c+1,其中c为使最后一项>0的最大整数
k -= c;
W[++cnt] = c * w;
// cnt++;
V[cnt] = c * v;// 拆分后的大米重量和价格均为组成该物品的大米的重量价格和
c *= 2;
}
W[++cnt] = w * k;
// cnt;
V[cnt] = v * k;
}
// init dp[] dp fill in 0 默认就是0,可以省略
for (int i = 1; i <= n; i++) {
dp[i] = 0;
}
for (int i = 1; i <= cnt; i++) {
for (int j = n; j >= W[i]; j--) {
dp[j] = Math.max(dp[j], dp[j - W[i]] + V[i]);
}
}
System.out.println(dp[n]);
}
}