AcWing 5. 多重背包问题 II【Java】
原题链接
中等
作者:
赤赤之龙
,
2020-02-27 01:18:46
,
所有人可见
,
阅读 944
/*
幂分解的思路参考大神文章
https://www.acwing.com/solution/acwing/content/3988/
*/
import java.util.Scanner;
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int N = input.nextInt();
int V = input.nextInt();
// si <= 20000,使用二进制表示时最多15bit,因此乘N为15000即所需数组的最大值
// 可以考虑使用List<Integer>来装输入
int[] vol = new int[15000];
int[] val = new int[15000];
int count =1;
for(int i = 1; i< N + 1; i++){
vol[count] = input.nextInt();
val[count] = input.nextInt();
int origin = count;
int k = input.nextInt();
// m为2的幂次
int m = 1;
// k以2为底幂分解
while(k > m){
vol[count] = m*vol[origin];
val[count] = m*val[origin];
k -= m;
m = m << 1;
count++;
}
// 对于k而言,至少为1,因此count++至少执行一次,如果k == 1,则以下判定相当于执行自我赋值
if(k > 0){
vol[count] = k*vol[origin];
val[count] = k*val[origin];
count++;
}
}
// 输入数据处理完毕之后,到此转化为01背包问题
int[] dp = new int[V + 1];
// 此处count的最终值代表了有效数值的vol.length,数组其他值为初始值0,另外的,如果使用List,则无需count计数
for(int i = 1; i < count; i++){
for(int j = V; j >= vol[i]; j--){
dp[j] = Math.max(dp[j],dp[j - vol[i]] + val[i]);
}
}
System.out.println(dp[V]);
}
}