背包问题之多重背包

概述

相比完全背包问题,多重背包指定物品个数。我们可以将多重背包问题转化为0-1背包(容易超时,优化后续补充)进行处理。
求最好价值问题的多重背包不能使用记录使用物品次数的方式进行简化

例题

题目

给定一些不同价值的硬币,求这些硬币可以组成1~N范围内值的数量。

代码

public int backpack(int n,int[] value,int[] amount){
    boolean[] dp = new boolean[n + 1];
    dp[0] = true;
    int res = 0;
    for(int i = 0;i < value.length;i++){
        for(int j = 0;j < amount[i];j++){//根据物品数量将多重背包问题转化为0-1背包问题
            for(int k = n;k >= value[i];k--){
                if(!dp[k] && dp[k - value[i]])
                    res++;
                dp[k] = dp[k - value[i]] || dp[k];
            }
        }
    }
    return res;
}

一种特殊的优化方式,只适用于本题这种求true/false的,不适用于求最优值类型的问题,因为多重背包问题在做正序枚举的时候虽然能够记录之前的最优解的物品使用次数,但后续当前解由于受到物品使用限制可能会需要使用使用次数较少的之前的最优解,但得不到,所以不能进行此优化方法,个人认为,此优化方法不重要,了解即可。

public int backpack_improved(int n,int[] value,int[] amount){
    boolean[] dp = new boolean[n + 1];
    int[] cnt = new int[n + 1];//记录当前解使用物品的次数
    int res = 0;
    dp[0] = true;
    for(int i = 0;i < value.length;i++){
        for(int j = value[i];j <= n;j++){
            if(!dp[j] && dp[j - value[i]] && cnt[j - value[i]] < amount[i]){
                res++;
                dp[j] = true;
                cnt[j] = cnt[j - value[i]] + 1;
            }
        }
    }
    return res;
}

优化

待完成

猜你喜欢

转载自www.cnblogs.com/wunsiang/p/12765088.html