背包问题-三种动态规划解法-逐步减少空间复杂度
题目描述:有编号分别为1,2,3,4,5的五件物品,它们的重量分别是2,2,6,5,4,它们的价值分别是6,3,5,4,6,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
背包问题是典型的动态规划问题,也有一定的规律可循,通常采用自底向上的方式,先解决小问题,并存储,再解决大问题。
方法一:时间空间都为O(n^2)的解法,但可以得到最大价值情况下拿了哪些东西
这里dp[i][j]的含义是:在只有i个物品,最大容量为j时,能获得的最大价值
def bag(weight, value, max_W):N = len(weight)V = max_Wdp = [[0 for i in range(V+1)] for j in range(N+1)]for i in range(1,N+1):for j in range(1,V+1):if weight[i-1]<=j:dp[i][j] = max(dp[i-1][j],dp[i-1][j-weight[i-1]]+value[i-1])else:dp[i][j] = dp[i-1][j]for i in range(N+1):print(dp[i][:])return dpdef thing(weight,value,max_W,dp): # 找出具体选了那些物品,这个可以参考第一个链接N = len(weight)V = max_Wthing_flag = [0 for i in range(N)]j = Vfor i in range(N,0,-1):if dp[i][j] != dp[i-1][j]:thing_flag[i-1]=1j -= weight[i-1]print(thing_flag)weight = [2,2,6,5,4]
value = [6,3,5,4,6]
max_W = 10
dp = bag(weight, value, max_W)
thing(weight,value,max_W,dp)
这个例子中对应的dp矩阵如下所示
可以通过从右下角向上回溯得到所有拿了的物品,见thing函数。
图片参考自:https://blog.csdn.net/superzzx0920/article/details/72178544
方法二:时间为O(n^2),空间为O(2n)的解法
如果不需要求出具体选了哪些物品而只要最大价值,那在空间上还可以继续优化,因为我们求解dp[i]时,只用到了上一个子问题dp[i-1],所以存储两个一维数组即可。
def bag(weight, value, max_W):N = len(weight)V = max_Wdp = [0 for i in range(V)]dp_next = [0 for i in range(V)]for i in range(N):for j in range(V):if weight[i]<=j:dp_next[j] = max(dp[j],dp[j-weight[i]]+value[i])dp = dp_next.copy() #注意这里要用.copy(),因为不用就是浅复制print(dp_next)return dp
方法三:时间为O(n^2),空间为O(n)的解法
再进一步思考,计算dp[i][j]时只使用了dp[i-1][0……j],没有使用dp[i-1][j+1]这样的话,我们先计算 j 的循环时,让j=V……1,即反方向计算,只使用一个一维数组即可。
def bag(weight, value, max_W):N = len(weight)V = max_Wdp = [0 for i in range(V)]for i in range(N):for j in range(V-1,-1,-1):if weight[i]<=j:dp[j] = max(dp[j],dp[j-weight[i]]+value[i])print(dp)return dp
背包问题-三种动态规划解法-逐步减少空间复杂度相关推荐
- 快排三种基本解法以及两种快排优化
/* 快速排序 基本思想 选定每次排序的基准数据 在剩下的位置将小于基准值的数据放在基准值得左边,大于基准值的数据放到基准值的右边 一次划分之后 如果此基准值的左右两边仍存在大于两个数 ...
- (左神)数据结构与算法 ---- 判断链表是否为回文结构的三种高效解法
链表在数据结构与算法中可谓"北斗之尊",现在让我们通过判断链表回文的小练习进一步更深地了解链表~ 文章目录 一.链表的节点结构 二.判断一个链表是否为回文结构 (一)解法1:将链表 ...
- 算法-连续项的最大和问题(最大子数组问题)三种不同解法
连续项的最大和问题 (1)暴力求解 时间复杂度 O(n^2) (2)分治求解 时间复杂度 O(nlogn) (3) 线性求解 时间复杂度 O(n) C#代码 using System; using S ...
- 隐马尔科夫模型,第三种问题解法,维比特算法(biterbi) algorithm python代码
上篇介绍了隐马尔科夫模型 本文给出关于问题3解决方法,并给出一个例子的python代码 回顾上文,问题3是什么, 下面给出,维比特算法(biterbi) algorithm 下面通过一个具体例子,来说 ...
- 0-1背包问题详解(DP分支限界回溯三种方法)
0-1背包 将n个项目的权重和值,放入一个容量为W的背包中,得到背包中最大的总价值.换句话说,给定两个整数数组val[0..n - 1]和wt [0 . .n-1],分别表示与n个项目相关的值和权重. ...
- 背包问题动态规划解法
一:题目: 背包问题 问题:两个数组 一个重量数组W 一个 价值数组 V 一个背包 bag ,返回不超过背包容量返回最大价值 二:暴力解法 思路:暴力遍历,思路就是递归的时候 按 选或者不选 当前 ...
- 两数之和(JavaScript三种算法)
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那 两个整数,并返回它们的数组下标. 你可以假设每种输入只会对应一个答案.但是,数组中同一个 ...
- c语言中二叉树中总结点,C语言二叉树的三种遍历方式的实现及原理
二叉树遍历分为三种:前序.中序.后序,其中序遍历最为重要.为啥叫这个名字?是根据根节点的顺序命名的. 比如上图正常的一个满节点,A:根节点.B:左节点.C:右节点,前序顺序是ABC(根节点排最先,然后 ...
- 搭上AI这趟车!用人工智能进行市场营销的三种方法
全文共1815字,预计学习时长5分钟 图源:Google 随着人工智能的发展,没人想让自己的市场营销策略落后于人,尤其对于科技巨头和当代的初创企业来说.这就导致了一些令人费解的问题出现.其中一些问题包 ...
最新文章
- 《Redis官方文档》用Redis构建分布式锁
- Response.Redirect() 跳转中的ThreadAbortException
- 多个硬件体验如一,华为终端分布式技术会重构IoT生态吗?
- 【转】Azure DevOps —— Azure Board 之 长篇故事、特性、用户情景(故事)的用法应用场景
- es6一维数组转二维数组_技术图文:Numpy 一维数组 VS. Pandas Series
- oracle数据库密码复杂度查询,Oracle11g R2创建PASSWORD_VERIFY_FUNCTION对应密码复杂度验证函数步骤...
- 用Java描述数据结构之栈和队列,以及栈和队列的常用方法
- 动态污点分析——隐式流造成的漏报和误报
- leetcode题解776-旋转字符串
- 在LINUX系统中安装KVM虚拟化
- Atitit 输入法原理与概论ati use
- ios音视频开发路线及技术点
- Java实现微信扫一扫
- 关于集训7教机房没网络 问题的解决方案
- 小程序scroll-view,滚动到最低_小程序滚动到底部
- 科技云报道:FONE:半年融资过亿元,打造EPM领域“最强国货”
- GPA计算器beta1
- 三足鼎立写博赚钱之道--献给2010年初互联网扫黄运动被错杀的兄弟
- C++多线程技术--API
- genl_ops结构分析