多重背包
对于每件物品,不是放或不放的问题,同时每件物品也不是可以无限次的使用,而是给定一个序列,规定每个物品的件数,所以背包中的物品除了重量的约束外,还有物品件数的约束
-
思路一:将多重背包转换为0-1背包。比如,有2件价值为5,重量为2的同一物品,我们就可以分为物品a和物品b,a和b的价值都为5,重量都为2,但我们把它们视作不同的物品。
public class duochongback {
public static int back(int[] a,int[] v,int[] n,int m){
int sum = sum(n);
int[] a1 = new int[sum];
int[] v1 = new int[sum];
for(int i = 0;i<a.length;i++)
a1[i] = a[i];
for(int i = 0;i<v.length;i++)
v1[i] = v[i];
int k = a.length;
for(int i = 0;i<n.length;i++){
while(n[i]!=1){
a1[k] = a[i];
v1[k] = v[i];
k++;
n[i]--;
}
}
int[] dp = new int[m+1];
for(int i = 0;i<a1.length;i++){
for(int j = m;j>=a1[i];j--)
dp[j] = Math.max(dp[j],dp[j-a1[i]]+v1[i]);
}
return dp[m];
}
public static int sum(int[] n){
int sum = 0;
for(int x:n)
sum += x;
return sum;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int[] a = {1,2,3};
int[] v = {2,1,4};
int[] n = {5,4,2};
int m = 6;
int value = back(a,v,n,m);
System.out.println(value);
}
}
时间复杂度为O(NVM),V代表重量,V代表价值,M代表数量
- 思路二:将多重背包转换为完全背包,状态转移方程:
/*多重背包转化为完全背包
* coded by Jerome
*/
public class duochongbeibao1 {
public static int[] a = {1,2,3};//重量
public static int[] v = {2,1,4};//价值
public static int[] n = {5,4,2};//数量
public static int m = 6;
public static int back(int[] a,int[] v,int[] n,int m){
int value = fun(a.length-1,m);
return value;
}
public static int fun(int i,int m){
if(i == 0)
return(m/a[i]<n[i]?m/a[i]:n[i])*v[i];
else{
int x = (m/a[i]<n[i]?m/a[i]:n[i]) + 1;
int[] dp = new int[x];
for(int j = 0;j<x;j++)
dp[j] = fun(i-1,m-j*a[i])+j*v[i];
return max(dp);
}
}
public static int max(int[] dp){
int index = 0;
if(dp.length == 0)
return -1;
for(int i = 1;i<dp.length;i++){
if(dp[i]>dp[index])
index = i;
}
return dp[index];
}
public static void main(String[] args) {
// TODO Auto-generated method stub
int value = back(a,v,n,m);
System.out.println(value);
}
}