0-1背包问题

0-1背包问题

1.问题描述

现有n种物品和一个背包
物品i的重量是Wi, 价值是Vi, 背包容量是c
如何选择物品,才能使得背包中的物品价值之和最大

2. 分析思路

  • 模型: sum(Vi*Xi) , sum(Wi*Xi) <= c , xi取值为0或者1
  • 递归求解,对于物品序列 Item1, Item2, Item3,……, Itemi,考察Itemi是否放入背包,假设此时背包容量为j, 背包的最优价值为m(i,j)
  • j < Wi,说明 Itemi根本放不进去,最优值是m(i-1, j)
  • j >= Wi 存在两种情况 Itemi放进去和Itemi不放进去,Itemi不放进去,最优值是m (i-1,j), Itemi放进去,最优值是m(i-1, j-Wi) + Vi,
    最后取最大值即可 ,最优值是Math.max(m(i-1, j), m(i-1, j - Wi) + Vi)

3. 实现

package packbag;

/**
 * @Author Fizz Pu
 * @Date 2020/10/27 下午11:29
 * @Version 1.0
 * 失之毫厘,缪之千里!
 */


public class packbag0_1 {
    public static void main(String[] args) {
        
        // bagSize 背包容量
        // itemCount 物品个数
        int bagSize = 10, itemCount = 5;
        int[] weight = new int[] {2,2,6,5,4};
        int[] value = new int[] {6,3,5,4,6};

        // 背包容量从0开始
        int[][] dp = new int[itemCount][bagSize+1];

        // 初始化值,只有一个物品时
        for(int i = 0; i <= bagSize; ++i){
            int itemValue = value[0], itemWeight = weight[0];
            dp[0][i] = (i < itemWeight ? 0 : itemValue);
        }

        // 利用状态转移方程填表
        for(int itemIndex = 2; itemIndex <= itemCount; ++itemIndex){
            for(int bagWeight = 1; bagWeight <= bagSize; ++bagWeight){
                int weightI = weight[itemIndex-1], valueI = value[itemIndex-1];
                dp[itemIndex-1][bagWeight] = (bagWeight < weightI ? dp[itemIndex-2][bagWeight] :
                        Math.max(dp[itemIndex-2][bagWeight], dp[itemIndex-2][bagWeight-weightI] + valueI));
            }
        }
        
        // 打印最优值
        System.out.println(Arrays.deepToString(dp));
    }
}

4. 继续思考

  • 如何通过最优值找到最优的选择方案
  • 时间复杂度是多少,如何优化算法
posted @ 2021-05-27 21:16  FizzPu  阅读(45)  评论(0编辑  收藏  举报