Java实现动态规划背包问题

 更新时间:2021年06月21日 17:03:25   作者:Abro.  
本文主要介绍使用java实现动态规划的背包问题,详细使用图文和多种案例进行解析,帮助理解该算法

前言

给定 n n n 种物品和一个背包。物品 i i i 的重量是 w i wi wi,其价值为 v i vi vi,背包的容量为 c c c。问应如何选择装入背包的物品,使得装入背包中物品的总价值最大?

一、原理

0 − 0 - 0− 1 1 1 背包问题是一个特殊的整数规划问题。

在这里插入图片描述

1.1 最优子结构性质

在这里插入图片描述在这里插入图片描述

1.2 递归关系

在这里插入图片描述

设所给 0 − 1 0-1 0−1 背包问题的子问题的最优值为 m(i,j),即 m(i,j)是背包容量为 j,可选择物品为 i,i+1,…,n 时 0-1背包问题的最优值。由 0-1背包问题的最优子结构性质,可以建立计算 m(i,j)的递归式如下:

在这里插入图片描述

在这里插入图片描述

二、算法描述

2.1 算法描述

在这里插入图片描述

伪代码:

在这里插入图片描述

2.2 图解

在这里插入图片描述

在这里插入图片描述

2.3 构造最优解

在这里插入图片描述
在这里插入图片描述


三、 0 − 1 0-1 0−1 背包问题相关题目

3.1 题目

已知有5个物体,它们的重量分别为:2,2,4,5,4,各物体的价值依次为6,3,5,4,6,背包大小为10,使用动态规划法求矩阵m[i][j],并给出最优解。修改数据为:5个物体,它们的重量分别为:1,1,2,3,2,各物体的价值依次为6,3,5,4,6,背包大小为6,使用动态规划法求矩阵m[i][j],并给出最优解

3.2 源程序(Java求解 0 − 1 0-1 0−1背包问题)

/**
 * 0-1背包问题(动态规划法求解)
 */
public class E3_9 {
    //物品的个数+1(第一个数我写成0)
    static int N = 6;
    //static int C = 7;
    static int C = 11;
    /**
     * 程序的入口
     * @param args
     */
    public static void main(String[] args) {
        //int n = N-1;
        //背包的容量
        int c = C-1;
        int i;
        //物体的重量
        //int w[] = new int[N];
        int w[] = new int[]{0,2,2,4,5,4};
        //int w[] = new int[]{0,1,1,2,3,2};
        //物体的价值
        //int v[] = new int[N];
        int v[] = new int[]{0,6,3,5,4,6};
        //动态规划法求解过程的矩阵
        int m[][] = new int[N][C];
        //选择的结果
        int x[] = new int [N];

        // for (i = 1; i < N; i++) {
        //     w[i] = 1+(int) (Math.random()*5);
        //     v[i] = 1+(int) (Math.random()*10);
        // }

        knapsack(v,w,c,m);
        traceback(m,w,c,x);

        System.out.printf("背包能装的最大价值为:"+"%d  \n ",m[1][c]);
        for (i = 1; i <= c; i++) {
            System.out.printf("%2d  \t",i);
        }
        System.out.printf("重量 价值\n");

        for (i = 1; i < N; i++) {
            System.out.printf("%d:",i);
            for (int j = 1; j <= c; j++) {
                System.out.printf("%2d  \t",m[i][j]);
            }
            System.out.printf("%2d%4d\n",w[i],v[i]);
        }
        System.out.printf("\n\n物品的重量");
        for (i = 1; i < N; i++) {
            System.out.printf("%2d   \t",w[i]);
        }
        System.out.printf("\n物品的价值");
        for (i = 1; i < N; i++) {
            System.out.printf("%2d   \t",v[i]);
        }
        System.out.printf("\n选择的结果");
        for (i = 1; i < N; i++) {
            System.out.printf("%2d   \t",x[i]);
        }
        System.out.printf("\n");
    }

    /**
     * 由0-1背包问题的最优子结构性质建立的递归式
     * @param v 存储物品价值的数组
     * @param w 存储物品重量的数组
     * @param c 背包容量
     * @param m 动态规划法求解过程的矩阵
     */
    public static void knapsack(int []v,int []w,int c,int [][]m){
        int n=v.length-1;
        int jMax=Math.min(w[n]-1,c);
        for(int j=0;j<=jMax;j++)  m[n][j]=0;
        for(int j=w[n];j<=c;j++)  m[n][j]=v[n];
        for(int i=n-1;i>0;i--){
            jMax=Math.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]=Math.max(m[i+1][j],m[i+1][j-w[i]]+v[i]);
        }
        //m[1][c]=m[2][c];
        //对于i=1时的两种情况
        if(c>=w[1])
            m[1][c]=Math.max(m[2][c],m[2][c-w[1]]+v[1]);
        else
            m[1][c]=m[2][c];
    }

    /**
     * 构造最优解
     * @param m 动态规划法求解过程的矩阵
     * @param w 存储物体的重量的数组
     * @param c 背包容量
     * @param x 存储选择结果的数组
     */
    public static void traceback(int [][]m,int []w,int c,int []x){
        int n=w.length-1;
        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;
    }
}

3.3 运行结果

在这里插入图片描述

在这里插入图片描述


总结

动态规划基本步骤

  • 找出最优解的性质,并刻划其结构特征。
  • 递归地定义最优值。
  • 以自底向上的方式计算出最优值。
  • 根据计算最优值时得到的信息,构造最优解。

到此这篇关于Java实现动态规划背包问题的文章就介绍到这了,更多相关java动态规划内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 解决springboot+shiro 权限拦截失效的问题

    解决springboot+shiro 权限拦截失效的问题

    这篇文章主要介绍了解决springboot+shiro 权限拦截失效的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-09-09
  • Java AQS中闭锁CountDownLatch的使用

    Java AQS中闭锁CountDownLatch的使用

    CountDownLatch 是一个同步工具类,用来协调多个线程之间的同步,它能够使一个线程在等待另外一些线程完成各自工作之后,再继续执行。被将利用CountDownLatch实现网络同步请求,异步同时获取商品信息组装,感兴趣的可以了解一下
    2023-02-02
  • 列举java语言中反射的常用方法及实例代码

    列举java语言中反射的常用方法及实例代码

    反射机制指的是程序在运行时能够获取自身的信息。这篇文章主要介绍了列举java语言中反射的常用方法,需要的朋友可以参考下
    2019-07-07
  • 浅谈java 字符串,字符数组,list间的转化

    浅谈java 字符串,字符数组,list间的转化

    下面小编就为大家带来一篇浅谈java 字符串,字符数组,list间的转化。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-11-11
  • Java基础篇之分布式版本控制工具Git

    Java基础篇之分布式版本控制工具Git

    Git是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。 也是Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件
    2021-10-10
  • spring boot 使用 @Scheduled 注解和 TaskScheduler 接口实现定时任务

    spring boot 使用 @Scheduled 注解和 TaskScheduler 接口实现定时任务

    这篇文章主要介绍了spring boot 使用 @Scheduled 注解和 TaskScheduler 接口实现定时任务,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-06-06
  • Java 微信公众号开发相关总结

    Java 微信公众号开发相关总结

    公众号作为主流的自媒体平台,有着不少人使用。这次以文本回复作为案例来讲解Java相关的微信公众号开发
    2021-05-05
  • Java Spring 控制反转(IOC)容器详解

    Java Spring 控制反转(IOC)容器详解

    这篇文章主要为大家详细介绍了Spring控制反转IoC入门使用的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10
  • RabbitMQ消息队列中的Channel信道参数详解

    RabbitMQ消息队列中的Channel信道参数详解

    这篇文章主要介绍了RabbitMQ消息队列中的Channel信道参数详解,信道是生产消费者与rabbit通信的渠道,生产者publish或者消费者消费一个队列都是需要通过信道来通信的,信道是建立在TCP上面的虚拟链接,需要的朋友可以参考下
    2023-08-08
  • java解析XML Node与Element的区别(推荐)

    java解析XML Node与Element的区别(推荐)

    下面小编就为大家分享一篇java解析XML Node与Element的区别,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-01-01

最新评论