| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 数据结构与算法 -> 01背包输出路径、完全背包、多重背包 -> 正文阅读 |
|
[数据结构与算法]01背包输出路径、完全背包、多重背包 |
背包问题一、01 Knapsack(输出路径- >选的物品)
二、完全背包1、三重循环,极可能TLE,滚动数组优化后j逆向枚举
(如果这种三重循环暴力的方法不超时,且欲将其优化成一维数组,枚举j时要像0-1背包一样逆向噢,因为状态转移方程max第二项是
d
p
【
i
?
1
】
dp【i-1】
dp【i?1】 2、二重,优化消去变量k(没有特别厘清,但可以直接从完全背包角度理解,取完一个还可以取无数个)a.不装入第i种物品,即
d
p
[
i
?
1
]
[
j
]
dp[i?1][j]
dp[i?1][j],同01背包;
或者
这个状态转移方程与01背包问题唯一不同就是max第二项不是dp[i-1]而是dp[i]。 3、滚动数组优化成一维数组,j正向枚举和01背包问题类似,也可进行空间优化,优化后不同点在于这里的 j 只能正向枚举而01背包只能逆向枚举,因为这里的max第二项是dp[i]而01背包是dp[i-1],即这里就是需要覆盖而01背包需要避免覆盖。
01背包和完全背包问题此解法的空间优化版解法唯一不同就是前者的 j 只能逆向枚举而后者的 j 只能正向枚举,这是由二者的状态转移方程决定的 三、背包恰好装满的情形为什么 d p [ m ] dp[m] dp[m]是能取到得最大价值,因为一开始对dp数组进行初始化时,将dp数组所有元素都初始化为0了, d p [ m ] dp[m] dp[m]可能并非由 d p [ 0 ] dp[0] dp[0]这个状态庄毅而来,可能是由中途某个 d p [ k ] dp[k] dp[k]转移而来 如果问,恰好占用了m这么多的背包容量 这一条件下能取得得最大价值,就在初始化dp数组时,将dp【0】初始化为0,其余都初始化为负无穷 解释二则:现在考虑动态规划的初始值问题。 如果没有恰好装满背包的限制,我们将dp全部初始化成0就可以了。因为任何容量的背包都有一个合法解“什么都不装”,这个解的价值为0,所以初始时状态的值也就全部为0了。如果有恰好装满的限制,那只应该将dp[0,…,N][0]初始为0,其它dp值均初始化为-inf,因为此时只有容量为0的背包可以在什么也不装情况下被“恰好装满”,其它容量的背包初始均没有合法的解,应该被初始化为-inf。 ?为什么不能初始化为0,让0和背包装满时的dp正数值进行区分呢?由以上图表可见,dp数组的值
d
p
【
i
】
【
j
】
dp【i】【j】
dp【i】【j】表示的含义是对于前i件商品,能否装满容量为j的背包,能装满的话
d
p
【
i
】
【
j
】
dp【i】【j】
dp【i】【j】表示装满时的最大价值。 四、多重背包问题Ⅰ(数据小,拆成0-1背包)
1、将多重背包一个一个拆出来,拆成0—1背包将多重背包拆成0—1背包要注意的是这时数组最大容量不能由商品种类数决定,而是总建树=种类*件数
2、直接加一层循环,枚举每件商品的件数三重循环的层次不能变,可能跟滚动数组中那种求值顺序有关?×
五、多重背包问题Ⅱ(二进制优化划分)数据范围增大,三重循环会超时 给定一个数s, 问最少可以把s分成多少个数,并把这些数拼成小于等于s的所有的数? 以 9 为例,先划分出一个1,再划分出 2,再划分出 4,最后剩下了一个 2,2小于8,就需要单独划分为一堆。 采用二进制思路将第 i 种物品分成
O
(
l
o
g
S
i
)
O(logS_i)
O(logSi?)件物品,将原问题转化为了复杂度为 的 01 背包问题
六、二维背包(有两个对于背包的限制,不止容量还有体积啥的)前面讨论的背包容量都是一个量:重量。二维背包问题是指每个背包有两个限制条件(比如重量和体积限制),选择物品必须要满足这两个条件。此类问题的解法和一维背包问题不同就是dp数组要多开一维,其他和一维背包完全一样 题目们474. 一和零题目链接
416. Partition Equal Subset Sum题目链接 一个正整数数组是否可以 划分为两个元素之和相等的子集 可以回答为什么初始化dp数组为负无穷而不是-1甚至0了 上面提出疑问时就说了,既然得到某个容量背包的价值时首先对该容量的确定,是取若干个商品的组合(取几个商品的体积之和S,对应的容量为S的背包自然可以被装满),当然了,这个取几个商品组合的过程是通过有条件的递推,什么条件呢?就是要从 能被装满的背包的价值 的基础上,遍历后来的商品,取或不取 就是相当于,
状
态
d
p
[
j
]
由
状
态
d
p
[
j
?
n
u
m
[
i
?
1
]
]
状态dp[j]由状态dp[j-num[i-1]]
状态dp[j]由状态dp[j?num[i?1]]推出来,那么
d
p
[
j
?
n
u
m
[
i
?
1
]
]
dp[j-num[i-1]]
dp[j?num[i?1]]这个状态就要是存在的,有意义的 这里对dp数组没有意义的值设置为负无穷,是为了在执行状态状态转移方程时,
方便判断 而对初始没有意义的值初始化为负无穷,就可以借助方程中天然的max函数(本来是判断第二个条件的)来筛掉不满足第一个条件的状态
1、初始化为-1
2、初始化为负无穷(
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/26 16:32:27- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |