0-1背包问题(动态规划、Java)

package com.ltcode.ds;

/**
 * @author LT
 * @github [https://github.com/ltcodes] [https://gitee.com/fltcode]
 * @date 2021/4/21 - 15:33
 * @description 基于动态规划算法的0-1背包问题设计过程与实现
 */

public class Backpack {
    // 定义物品种类
    static int n = 5;
    // 存储每件物品的重量w[i],下标从1开始
    static int[] w = {0, 2, 2, 6, 5, 4};
    // 存储每件物品的价值v[i]
    static int[] v = {0, 6, 3, 5, 4, 6};
    // 定义背包容量
    static int c = 8;
    // 存储m(i, j)相对应的值
    static int[][] m = new int[10][10];
    // 存储装入或不装入
    static int[] x = new int[n + 1];

    public static void knapsack(){
        // 计算背包的剩余容量上限,范围[0 ~ w[n]-1]
        int jMax = min(w[n]-1, c);
        // 当0<=j<=w[n]时,m(n,j)=0
        for (int j = 0; j <= jMax; j++) {
            m[n][j] = 0;
        }
        // 当j>=w[n]时,m(n,j)=v[n]
        for (int j = w[n]; j <= c; j++) {
            m[n][j] = v[n];
        }
        // 从n-1往前开始判断第n个物品到第i个物品能不能装下
        for (int i = n-1; i > 1; i--) {
            jMax = min(w[i]-1, c);
            for (int j = 0; j <= jMax; j++) {
                m[i][j] = m[i+1][j];
            }
            for (int j = w[i]; j <= c; j++) {
                m[i][j] = max(m[i+1][j], m[i+1][j-w[i]]+v[i]);
            }
        }
        // 判断第n个到第1个物品能不能装下
        m[1][c] = m[2][c];
        if (c >= w[1]) {
            m[1][c] = max(m[1][c], m[2][c-w[1]]+v[1]);
        }
    }
    // 回溯查找最优序列,能装下的赋值为1,不能装下的赋值为0
    public static void traceBack(){
        for (int i = 1; i < n; i++) {
            if (m[i][c] == m[i+1][c]){
                x[i] = 0;
            } else {
                x[i] = 1;
                c -= w[i];
            }
        }
        x[n] = m[n][c] != 0 ? 1:0;
    }

    public static int min(int a, int b){
        return a < b ? a:b;
    }

    public static int max(int a, int b){
        return a > b ? a:b;
    }

    public static void main(String[] args) {
        System.out.print("待装物品重量分别为:");
        for (int i = 1; i <= n; i++) {
            System.out.print(i < n ? w[i] + ", " : w[i]);
        }
        System.out.println();

        System.out.print("待装物品价值分别为:");
        for (int i = 1; i <= n; i++) {
            System.out.print(i < n ? v[i] + ", " : v[i]);
        }
        System.out.println();

        knapsack();
        System.out.println("背包能装的最大价值为:" + m[1][c]);

        traceBack();
        System.out.print("最优装载序列为:");
        for (int i = 1; i <= n; i++) {
            System.out.print(i < n ? x[i] + ", " : x[i]);
        }
        System.out.println();
        System.out.print("背包装下的物品编号为:");
        for (int i = 1; i <= n; i++) {
            if (x[i] == 1) {
                System.out.print(i < n ? i + ", " : i);
            }
        }
        /**
         * 结果如下:
         * 待装物品重量分别为:2, 2, 6, 5, 4
         * 待装物品价值分别为:6, 3, 5, 4, 6
         * 背包能装的最大价值为:15
         * 最优装载序列为:1, 1, 0, 0, 1
         * 背包装下的物品编号为:1, 2, 5
         */
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值