多重背包

多重背包

对于每件物品,不是放或不放的问题,同时每件物品也不是可以无限次的使用,而是给定一个序列,规定每个物品的件数,所以背包中的物品除了重量的约束外,还有物品件数的约束

  • 思路一:将多重背包转换为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);
        }

    }

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值