Java之动态规划的背包问题

这篇具有很好参考价值的文章主要介绍了Java之动态规划的背包问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

动态规划问题

一:01背包问题

1.问题描述

2.分析问题

3.代码实现(二维数组)

4.滚动数组实现(一维数组)

二:完全背包问题

1.题目描述

2.问题分析

3.代码实现


动态规划问题

动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题,进行解决,从而一步步获取最优解的处理算法

动态规划对于解决最优子结构啊和重叠子问题等问题时候,有着很好的应用

对于动态规划问题,大致可以分为以下几步:

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

一:01背包问题

1.问题描述

有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

例如以下问题:

有一个背包,它的容量为4磅,现有以下物体

物品 重量 价格
物品0 1 1500
物品1 4 3000
物品2 3 2000

1)要求达到的目标为装入的背包的总价值最大,并且重量不超出                                                    2)要求装入的物品不能重复

2.分析问题

对于解决这样的动态规划的背包问题,还是采用通用的五个步骤

1.确定dp数组(dp table)以及下标的含义

对于01背包问题,可以采用二维数组或者一维数组,这里为了便于理解,先采用一维数组

定义一个二维数组dp[i][j],这里dp数组的含义为:将物品(0到i)放入到背包容量为j的背包里面,价值总和最大为dp[i][j]

2.确定递推公式

对于放入物品i,有两种状态:将物品i放入到背包中,不将物品i放入到背包中

不放物品i:不放物品i,相当于将物品0到i-1放入到背包容量为j的背包中,这个时候递推公式dp[i][j]就可以等于dp[i-1][j]

放物品i:当放入物品i的时候,此时首先需要判断的是否物品i可以放入到背包容量为j的背包中,要是使背包可以放入物品i,则背包的容量至少剩余weight[i],即放入物品0到i-1的时候,背包剩余的容量至少为j-weight[i],因此放入0到i-1物品的最大价值为dp[i-1][j-weight[i]],放入物品i时候的最大价值就为dp[i-1][j-weight[i]]+value[i]

此时dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])

3.dp数组如何初始化

由递推公式dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])可以看出,第i行需要由上一行推算出,所以第i=0行的数据一定要进行初始化,具体如下

        for (int i = weight[0]; i <= bagSize; ++i) {
            dp[0][i] = value[0];
        }

4.确定遍历顺序

实现先遍历背包还是先遍历物品,其实都可以,但是先遍历物品更好理解

确定递推的方向:

dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 递归公式中可以看出dp[i][j]是靠dp[i-1][j]和dp[i - 1][j - weight[i]]推导出来的,dp[i][j]是由其左上角的元素推出来的,因此需要自上到下,自左到右的遍历顺序

多重背包问题java,动态规划,动态规划,算法

5.举例推导dp数组

对dp数组进行填表的操作

0 1 2 3 4
0 0 1500 1500 1500 1500
1 0 1500 1500 1500 3000
2 0 1500 1500 2000 3500

3.代码实现(二维数组)

    public static int maxValue(int[] weight, int[] value, int bagSize) {
        int num = weight.length;
        int[][] dp = new int[num][bagSize + 1];//0-i物品任取到容量为j的背包的最大价值
        for (int i = weight[0]; i <= bagSize; ++i) {
            dp[0][i] = value[0];
        }
        for (int i = 1; i < num; ++i) {
            for (int j = 1; j <= bagSize; ++j) {
                if (j < weight[i]) {//如果当前物品的重量大于背包的容量
                    dp[i][j] = dp[i - 1][j];//不取当前的物品
                } else {
                    //dp[i - 1][j]不取当前的物品的价值,
                    //dp[i - 1][j - weight[i]] + value[i]取当前物品
                    dp[i][j] = Math.max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
                }

            }
        }
        return dp[num - 1][bagSize];

    }

4.滚动数组实现(一维数组)

在使用二维数组的时候,递推公式:dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

下一行的元素仅有上一行的元素推出来,因此可以使用滚动数组,也就是一维dp数组

1.确定dp数组(dp table)以及下标的含义

dp[j]表示背包容量为j的商品最大价值为dp[j]

2.确定递推公式

和二维dp数组一样,也是有两种选择,一种放入物品i,一种不放物品i,因此可以写成

此时dp[j]=max(dp[j],dp[j-weight[i]]+value[i])

3.dp数组如何初始化

根据递推公式可以看出dp[j]由此层推出,此时我们可以将dp初始化为0

4.确定遍历顺序

上面我们已经写过了二维dp数组,我们知道本层是由下上方的元素推出来的,现在我们采用的是一维dp数组,如果我们还是采用从左到右进行递推的话,后面的元素就可能因为前边元素的变化而变化,不是由上一层的元素推出来的了,相当于二维dp数组我们根据本层前边的元素推出本层后边的元素,这样就不符合我们想要表达的意思了,如何我们采用的是从右到左的遍历顺序的话,这样彼此之间就不会因为后边元素的改变而影响前边元素的改变了,相当于上一层的元素推出本层的元素

多重背包问题java,动态规划,动态规划,算法

这里是与二维dp数组最大的不同,需要自己理解清楚

5.举例推导dp数组

三次for循环的数据如下

第一次
0 1500 1500 1500 1500
第二次
0 1500 1500 1500 3000
第三次
0 1500 1500 2000 3500

 代码实现

    public static int maxValue(int[] weight, int[] value, int bagSize) {
        int[] dp = new int[bagSize + 1];//0-i物品任取到容量为j的背包的最大价值

        for (int i = 0; i < weight.length; ++i) {//物品的数量
            for (int j = bagSize; j >= weight[i]; --j) {//背包剩余的重量
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
            System.out.println(Arrays.toString(dp));

        }
        return dp[bagSize];

    }

二:完全背包问题

1.题目描述

有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。

例如如下问题:

有一个背包,它的容量为4磅,现有以下物体

物品 重量 价格
物品0 1 1500
物品1 4 3000
物品2 3 2000

完全背包问题与01背包问题基本相似,唯一的区别就是多重背包问题的物品数量是无限的

2.问题分析

01背包的滚动数组的遍历顺序是从右到左的,可以保证每个物品只被遍历一次,而完全背包问题每个物品可以被添加多次,因此需要进行从左到右进行遍历,可以确保每个物品有被多次添加的可能

举例推导dp数组文章来源地址https://www.toymoban.com/news/detail-831071.html

第一次
0 1500 3000 4500 6000
第二次
0 1500 3000 4500 6000
第三次
0 1500 3000 4500 6000

3.代码实现

    public static int perfectPackage(int[] weight, int[] value, int bagWeight) {
        int[] dp = new int[bagWeight + 1];
        for (int i = 0; i < weight.length; ++i) {
            for (int j = weight[i]; j <= bagWeight; ++j) {
                dp[j] = Math.max(dp[j], dp[j - weight[i]] + value[i]);
            }
        }
        return dp[bagWeight];

    }

到了这里,关于Java之动态规划的背包问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 动态规划DP之背包问题3---多重背包问题

    目录 DP分析: 优化:  二进制优化 例题:         01背包是每个物品只有一个,完全背包问题是每个物品有无限个。         那么多重背包问题就是 每个物品有有限个 。 有 N 种物品和一个容量是 V 的背包。 第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。 求解

    2024年03月20日
    浏览(33)
  • java实现0-1背包问题方案(动态规划-贪心算法-回溯-分支定界)

    动态规划算法时间复杂度较低,能够求解较大规模的问题,但空间复杂度较高,不适用于数据量较大的问题。 贪心算法时间复杂度较低,能够求解较大规模的问题,但不能保证求得的解是最优解。 回溯算法能够求解较小规模的问题,但时间复杂度较高,不适用于数据量较大

    2024年02月01日
    浏览(84)
  • 三十八、动态规划——背包问题( 01 背包 + 完全背包 + 多重背包 + 分组背包 + 优化)

    0 1 背包问题: 条件:N 个物品容量为 V 的背包,每件物品最多用 1 次,其中物品信息体积为 Vi,价值为 Wi。 目标:选出物品,使价值最大(不一定装满背包)。 特点:每件物品 最多只用 1 次 完全背包问题: 特点:每一件物品都有 无限个 多重背包问题: 特点:每个物品

    2024年02月07日
    浏览(33)
  • 动态规划-背包问题(java版)

    这篇文章主要讲两种基础的背包问题01背包和完全背包,其实主要是作者太菜。 首先来看一下问题描述 有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。 每件物品只能用一次 ,求解将哪些物品装入背包里物品价值总和最大。 此处

    2024年04月29日
    浏览(19)
  • 动态规划完全背包问题-java

    完全背包问题跟01背包问题思路大致一样,只不过对于物品的拿取次数不在限制,我们只需要考虑这点即可。 文章目录 前言 一、什么是完全背包问题? 二、问题模拟 1.样例数据 2.算法思路 三、代码如下 1.代码如下(示例): 2.读入数 3.代码运行结果 总结 完全背包问题跟

    2024年04月26日
    浏览(35)
  • Java之动态规划的背包问题

    目录 动态规划问题 一:01背包问题 1.问题描述 2.分析问题 3.代码实现(二维数组) 4.滚动数组实现(一维数组) 二:完全背包问题 1.题目描述 2.问题分析 3.代码实现 动态规划(Dynamic Programming)算法的核心思想是:将大问题划分为小问题,进行解决,从而一步步获取最优解的处理算法 动态

    2024年02月20日
    浏览(14)
  • 算法 DAY45 动态规划07 70. 爬楼梯 322. 零钱兑换 279. 完全平方数 139. 单词拆分 多重背包

    和377. 组合总和 Ⅳ (opens new window)基本就是一道题了。 本题代码不长,题目也很普通,但稍稍一进阶就可以考察完全背包 动态规划五部曲 1、确定dp[j]的含义 dp[j] 凑成 j 的最少硬币的个数 2、确定递推公式 比如想凑成3, 如果手里有1,那么最小个数就是dp[2]+1 如果手里有2,那

    2024年02月02日
    浏览(47)
  • Java数据结构与算法----动态规划(背包篇)

    1.1.算法思路 0/1背包是动态规划、背包问题中最经典的问题啦!它主要的问题是: 给定n种物品、这n种物品的重量分别是,价值分别是 ,而你有一个容量为C的背包,请问如何求出所能拿的最大价值呢? 对于动态规划,我们先需要找到一条推导公式,然后确定边界: 我们设

    2024年02月07日
    浏览(38)
  • 动态规划之多重背包模型

    前置知识:  01背包问题:动态规划之01背包模型_如何何何的博客-CSDN博客 完全背包问题:动态规划之完全背包模型_如何何何的博客-CSDN博客 给定一个有一定容量的背包,和 n 个物品,每个物品有 si 件; 每个物品有其对应的体积和价值; 问背包最多能装下的物品的最大价值

    2024年02月08日
    浏览(29)
  • 算法系列--动态规划--背包问题(3)--完全背包介绍

    💕\\\"Su7\\\"💕 作者:Lvzi 文章主要内容:算法系列–动态规划–背包问题(3)–完全背包介绍 大家好,今天为大家带来的是 算法系列--动态规划--背包问题(3)--完全背包介绍 链接: 完全背包 可以发现完全背包问题和01背包问题还是特比相似的 分析: 完全背包问题 是 01背包问题 的推广

    2024年04月25日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包