背包算法(一)-01背包-史上最详细解答
背包算法(一)-01背包-史上最详细解答
- 1. 题目
- 2. 分析
- 2.1 状态表示
- 2.2 状态计算
- 3. 实现
- 4. 优化
- 5. 测试
1. 题目
- 问题描述:有n件物品和容量为m的背包,给出i件物品的重量以及价值value,还有数量number,求解让装入背包的物品重量不超过背包容量W,且价值V最大 。
- 特点:这是最简单的背包问题,特点是每个物品只有一件供你选择放还是不放。
2. 分析
2.1 状态表示
一般用dp数组来计算动态规划问题,从以下两个方面对动态规划问题进行表示
集合
- v集合:物品价值
- w集合:物品重量
- 从前i个物品里面选取总重量<=j的所有物品的选法
属性
- max
- min
- count
本题属性是属于求最大价值,为max
2.2 状态计算
对于0和1背包的问题,我们计算的只是两个状态,即对于第i个物品选择放进去或者不放进去的问题。
- 选择放进去
表示在上一个物品的状态的时候,我的当前背包重量j需要减去当前这个物品的重量w[i],并且整个背包的价值需要加上当前这个物品的价值v[i],则状态方程为:
dp[i][j] = dp[i-1][j-w[i]] + v[i]
- 选择不放进去
实际上如果选择不放进去的时候,表示需要减去的w[i]和需要加上的v[i]都为0选择不放进去的状态方程则为:
# dp[i][j] = dp[i-1][j-0] + 0
dp[i][j] = dp[i-1][j]
由此我们可以得到状态转移方程:
dp[i][j] = max(dp[i-1][j-w[i]] + v[i], dp[i-1][j])
3. 实现
根据上面的状态转移方程我们可以得到01背包的二维解法:
def bag_two_2_0and1(items, weight):# 数据是从1开始的data_len = len(items)row = data_len + 1col = weight + 1# 生成二维数组# 原生的Python可以这么写:# dp = [[0] * col for _ in range(row)]# 使用numpy生成一个dp数组dp = np.array([0] * (row * col)).reshape(row, col)for i in range(1, row):if i == data_len:breakitem = items[i]v = item.get("value")w = item.get("weight")for j in range(1, col):if j >= w:no_input = dp[i-1][j]yes_input = dp[i-1][j-w] + vdp[i][j] = max(yes_input, no_input)else:dp[i][j] = dp[i-1][j]return dp[data_len-1][weight]
4. 优化
可以看的出来i这个变量其实就是表示“第i个”的一个递增序列,实际的这个背包的当前的状态只有重量(w)和价值(v)
根据刚才的状态方程:
# 不放进去
dp[i][j]=dp[i-1][j]# 放进去
dp[i][j]=dp[i-1][j-w[i]] + v[i]
观察两个状态方程,可以看到对于背包重量的状态j与i无关,因此可以把上述方程简化为:
# 不放进去时候,重量不变,价值不变
dp[j] = dp[j] # 放进去的时候,背包重量和价值的变化
dp[j] = dp[j-w[i]] + v[i]
因此可以得到状态转移方程为:
dp[j] = max(dp[j-w[i]] + v[i], dp[j])
根据上述的状态转移方程来实现代码:
def bag_one_dim_0and1(items, weight):# 数据是从1开始的data_len = len(items)row = data_len + 1col = weight + 1# 生成一维数组# 原生的Python可以这么写:# dp = [[0] * col]# 使用numpy生成一个dp数组dp = np.array([0] * col)for i in range(1, row):if i == data_len:breakitem = items[i]v = item.get("value")w = item.get("weight")for j in range(weight, w, -1):dp[j] = max(dp[j-w]+v, dp[j])return dp[weight]
【1】此处为何倒序遍历呢?
首先我们观察优化后和优化前的状态转移方程:
# 优化之前
dp[i][j] = max(dp[i-1][j-w[i]] + v[i], dp[i-1][j])# 优化之后
dp[j] = max(dp[j-w[i]] + v[i], dp[j])
因此实际上优化后的状态转移方程是:
dp[j](第i轮的新值) = max(dp[j-w[i]] + v[i](第i-1轮的旧值), dp[j](第i-1轮的旧值))
优化后的状态转移方程实际上就是用最新的值把上一轮的值覆盖掉,所以可以在一个一维数组中完成状态转移,而且得保证:这一轮状态只能是由上一轮的状态推出来的。
为什么需要逆序遍历,此处如果从背包问题的物理操作去解释不好解释,简单的从数学上去理解就是:
我们这个j-w[i]是做减法的,而这个j又是数组的下标,做减法之后就表示是之前的数据。由于需要用新的值把旧的值进行覆盖,就需要保证在此数据是没有被改动过的,也就是原封不动第i-1轮的数据与当前第i轮的数据进行比较。因此此处如果是顺序的话,这个数据就已经是第i轮更新的数据与第i轮的数据进行比较了。
5. 测试
我们给出01背包的测试数据
{'items': [{'number': 1,'weight': 49,'value': 241}, {'number': 1,'weight': 25,'value': 724}, {'number': 1,'weight': 91,'value': 780}, {'number': 1,'weight': 76,'value': 824}, {'number': 1,'weight': 92,'value': 968}, {'number': 1,'weight': 53,'value': 276}, {'number': 1,'weight': 6,'value': 492}, {'number': 1,'weight': 53,'value': 745}, {'number': 1,'weight': 62,'value': 136}, {'number': 1,'weight': 94,'value': 568}],'total_weight': 200,'things_num': 10
}
输出:
3008
下一章:背包问题(二)-完全背包-史上最详细解答
背包算法(一)-01背包-史上最详细解答相关推荐
- Spark MLlib机器学习 | 算法综合实战(一)(史上最详细)
========== ========= 8.1.1 什么是机器学习 机器学习可以看做是一门人工智能的科学,该领域的主要研究对象是人工智能.机器学习利用 ...
- 背包算法轻松搞定——01背包算法、部分背包算法
这篇文章过程讲得很详细,一文搞懂(点击看原文) 不懂之前觉得很难理解,觉得很复杂,其实没有必要.因为只要懂动态规划就可以很轻松搞定0-1背包算法(部分背包算法更简单,排序即可).之前看了很多篇文章都觉 ...
- 0-1背包算法和完全背包算法MATLAB代码实现
有10件物品,它们的重量分别是5,8,3,2,6,6,5,4,7,5,,它们的价值分别是2,4,7,7,3,6,3,5,4,6,现在给你个承重为30的背包,试用0-1背包.完全背包算法,分别计算如何让 ...
- 史上最详细“截图”搭建Hexo博客——For Windows
http://angelen.me/2015/01/23/2015-01-23-%E5%8F%B2%E4%B8%8A%E6%9C%80%E8%AF%A6%E7%BB%86%E2%80%9C%E6%88 ...
- IPV4与IPV6的区别(史上最详细)
IPV4与IPV6的区别(史上最详细) 描述 IPv4 IPv6 地址 长度为 32 位(4 个字节).地址由网络和主机部分组成,这取决于地址类.根据地址的前几位,可定义各种地址类:A.B.C.D 或 ...
- 史上最详细MySQL5.5复制配置步骤,与以前版本的有所不同
史上最详细MySQL5.5复制配置步骤,与以前版本的有所不同 http://codingstandards.iteye.com/blog/1535994 操作系统:CentOS 5.8 MySQL版本 ...
- 史上最详细唇语识别数据集综述
更新:VIPL官网网页格式更改,导致旧的LRW1000链接无法访问,现已更新LRW1000数据集链接,内部包含申请需要的文件 推荐一个大佬的综述,关于实现唇语识别的多种途径. 说明:本文包括经常用语唇 ...
- GitChat·大数据 | 史上最详细的Hadoop环境搭建
GitChat 作者:鸣宇淳 原文: 史上最详细的Hadoop环境搭建 关注公众号:GitChat 技术杂谈,一本正经的讲技术 [不要错过文末彩蛋] 前言 Hadoop在大数据技术体系中的地位至关重要 ...
- 史上最详细全中文 Cisco 3560交换机使用手册
史上最详细全中文 Cisco 3560交换机使用手册 (末尾送交换机安全技术) 目 录 CISCO Catalyst 3560-E系列交换机的功能应用及安全解决方案 3 一.Cisco? Cataly ...
最新文章
- Cloudstack系统配置(三)
- 如何部署同一个Spring boot web 应用到不同的环境
- java fast math,Java FastMath.signum方法代码示例
- vue 父组件获取接口值传到子组件_vue父组件异步获取数据传给子组件的方法
- (转)ATOM介绍和使用
- 如何能写出,一份让 HR 认同的简历
- scala Basic 第三课
- C#实现--单链表(链式)
- javascript变量说明
- DN值、地表反射率、 表观反射率、发射率、辐射亮度、亮温名词解释
- java图片的缩放_Java的图片自动缩放
- 服务器中硬盘JBOD模式和RAID0模式区别
- opencv 绿色通道提取
- 先将输入的一系列整数中的最小值与第一个数交换,然后将最大值与最后一个数交换,最后输出交换后的序列。
- Wait for me和waitting for me有什么区别?
- Go Context 原理详解
- Android 画闹钟
- 流程引擎之Flowable简介
- flutter 微信语言选择_#Flutter项目(3)之仿写微信通讯录界面
- 【附源码】计算机毕业设计java游泳馆管理系统设计与实现