01背包问题

public class Main {
    
    /**
     * 
     * @param value
     * @param weight
     * @param c 背包容量
     * @param m m(i,j)背包容量为j,可选择物品为i,i+1,...,n时背包的最优值
     */
    public static void knapsack(int[] value, int[] weight, int c, int[][] m){
        int n = value.length - 1;
        
        // 初始化:只选第n个物品的时候,背包容量范围的各个值的所选物品的最优值
        int jMax = Math.min(weight[n], c);
        for (int j = 0; j <= jMax; j++) {
            m[n][j] = 0;
        }
        for (int j = weight[n]; j < c; j++) {
            m[n][j] = value[n];
        }
        
        // 可选物品为i,i+1,...,n-1,背包容量范围各个值的所选物品的最优值
        for (int i = n - 1; i > 0; i--) {
            jMax = Math.min(weight[i], c);
            for (int j = 0; j < jMax; j++) {
                m[i][j] = m[i + 1][j];
            }
            for (int j = weight[i]; j < c; j++) {
                m[i][j] = Math.max(m[i + 1][j], m[i + 1][j - weight[i]] + value[i]);
            }
        }
        
        // 可选物品为1,2,...,n,背包容量为c的所选物品的最优值
        m[0][c] = m[1][c];
        if(c > weight[0]){
            m[0][c] = Math.max(m[0][c], m[1][c - weight[0]] + value[0]);
        }
    }
    
    /**
     * 获取最优解
     * @param m
     * @param weight
     * @param c
     * @param x
     */
    public static void traceback(int[][] m, int[] weight, int c, int[] x){
        int n = weight.length - 1;
        for (int i = 0; i < n; i++) {
            if(m[i][c] < m[i + 1][c]){
                x[i] = 0;
            }else{
                x[i] = 1;
                c -= weight[i];
            }
        }
        
        x[n] = m[n][c] > 0 ? 1: 0;
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
        int c = 10;
        int[] weight = {5, 5, 5};
        int[] value = {10,5,11};
        
        int[][] m = new int[weight.length][c + 1];
        knapsack(value, weight, c, m);
        
        int[] x={0,0,0};
        traceback(m, weight, c, x);
        
        System.out.println("最优值为:" + m[0][c]);
        
        System.out.print("最优解为:");
        for (int i = 0; i < x.length; i++) {
            System.out.print(x[i] + ((i != x.length - 1)? ",":""));
        }
        System.out.println("\n");
        
        System.out.println("最优值矩阵为:");
        for (int i = 0; i < weight.length; i++) {
            for (int j = 0; j < c + 1; j++) {
                System.out.print(m[i][j] + ((j != c) ? "," :""));
            }
            System.out.print("\n");
        }
    }

}

结果为:

最优值为:21
最优解为:1,1,0

最优值矩阵为:
0,0,0,0,0,0,0,0,0,0,21
0,0,0,0,0,11,11,11,11,11,0
0,0,0,0,0,11,11,11,11,11,0

转载于:https://www.cnblogs.com/kelin1314/p/4320107.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值