Subset Sum 问题单个物品重量限制前提下的更优算法
前言
看了 ShanLunjiaJian 关于这个问题的文章,是完全没看懂,沙东队爷的中枢神经内核配置把我偏序了。叉姐在下面提了个论文,论文找不到资源,谁搞到了可以 Q 我一份之类的拜谢了。然后找到了这个可能是阅读笔记或者是翻译的的东西,这下算是看懂了。
感觉还是很有意思,对于 DP 的状态设计、优化思路等都有很大启发,所以写一下。
(有单个物品重量限制的)Subset Sum 问题
ShanLunjiaJian 把这个叫做 Knapsack,我是要批判的,因为感觉上是带不了权的啊,这不是Knapsack!
那么描述一下这个问题:给定 \(n\) 个物品,每个物品有一个正整数重量 \(w_i\),保证 \(1\le w_i\le V\),其中 \(V\) 是所谓的重量限制。现在给一个容量 \(C\),取这些物品的一个子集,使得重量和不能超过这个容量,然后要求物品总重量的最大值,也就是让浪费的容量最小。
低论
这个问题显然有一个做法,叫做把它当作一个普通 Knapsack 问题,时间复杂度 \(\Theta(nC)\)。那么有意义的 \(C \le nV\)。所以其实上界是 \(n^2V\)。现在我们有高论!可以做到 \(\Theta(nV)\)。
高论
首先这个问题有一个经典贪心做法,叫做给所有元素从小到大排个序,然后选一个前缀使得再多选一个就会超过容量限制。这个做法当然是错的,但是可以基于它给出的这个既有选择方法去做调整,那么这样一来,剩余容量就是 \(\mathrm O(V)\) 的(如果大于 \(V\) 就一定可以再多选一个,矛盾了),很可做!
现在我们面临的问题是什么呢?我们的 DP 可能出现负数重量了(因为要支持取消选择一些原本选了的物品),这种条件下,要去维持我的剩余容量始终保持 \(\mathrm O(V)\),是有一点难度的。怎么办呢?
考虑一个直觉,是不是可以这样去操作:当试图去取消一个原先选的物品(也就是选负数)的时候,一定要让当前容量是超额的;当去选正数的时候,一定要让当前容量是不满的。考虑最优解是不是一定能用这种方式构造出来——显然是可以的。证明可以这样想,假设我从贪心生成的“基础解”开始,按照某个顺序去把它修正成最优解,是不是每一步都一定能按照上述规则操作。那么可以这样想:如果现在容量是超额的,但是不存在某个元素使得“最优解中没选它,当前解中选了它”,那么最优解选择的集合一定包含当前解,它的容量就一定也是超额的,矛盾,所以一定有办法去进行操作。反之亦然,因此按照这样的规则操作,必然能得到某种最优解。更棒的是,在这样操作的过程中,剩余容量始终在 \([-V, V]\) 以内!真是好极了,接下来只需要基于这种构造方案来 DP 就可以了。
先设计一个朴素 DP。设贪心得到的分界点为 \(p\),使得目前选择的集合是标号 \(\le p\) 的物品,\(S_0 = \sum\limits_{i = 1}^{p} w_i\)。那么设 \(g_{i, j, k}\) 表示右边决策到 \(i\),左边决策到 \(j\),当前剩余容量为 \(k \in [-V, V]\) 的方案是否存在。这个 DP 复杂度是 \(\Theta(n^2V)\),真是一点优化效果都没有!但是这个东西的进一步改造非常方便,这就是下一步的想法。
注意到这是一个值为 Boolean 类型的 DP,如果发现某一维具有单调性,那么就可以压缩掉这维。可以观察到:如果 \(g_{i, j, k} = 1\),那么对于任何 \(t \le j\),都有 \(g_{i, t, k} = 1\)——毕竟在左侧做出更多决策一定不会使可达集合变小。那么可以设 \(f_{i, k} = \max\{0 \le j \le p | g_{i, j, k} = 1\}\)。如果不存在这样的 \(j\),设为 \(-1\)。那么 DP 的初始条件是 \(f_{p+1, S_0} = p\)。转移如下:
f_{i+1, k + w_i} \gets f_{i, k}, & k \le 0 & (1)\\
f_{i+1, k} \gets f_{i, k}, & \text{any} & (2)\\
f_{i, k - w_t} \gets t - 1; & k \ge 0 \land t \le f_{i, k} & (3)
\end{cases}
\]
整体按照 \(i\) 递增转移,每个 \(i\) 按照 \(k\) 递减的方向做转移 (3) 即可。时间复杂度是 \(\Theta(n^2V)\),真是一点优化效果都没有!但是这个 DP 已经是 2D-1D 的了,进一步改造非常方便,这就是下一步的想法。
注意到只有转移 (3) 的复杂度不对,而这个转移很大程度上是重复的——某些转移过程,在 \(i = a\) 可以做,在 \(i = a - 1\) 同样可以做。那么可以尝试去掉这些转移,让本质相同的转移在最小的可以进行的 \(i\) 处去进行。注意到对于某个特定的 \(k\),关于某个特定的 \(t\) 的转移能否进行,只和 \(f_{i, k}\) 是否足够大有关,而我们有单调性 \(f_{i, k} \le f_{i+1, k}\),这是因为转移 (2) 的存在。所以转移 (3) 的条件可以改为 \(k \ge 0 \land f_{i-1, k} \le t \le f_{i,k}\)。这样一来,某个特定 \(k\) 对总复杂度的贡献是 \(\mathrm O(n)\) 的,所以总复杂度就变成了 \(\Theta(nV)\)!我们成功了!
后记
有人问有什么应用?我不知道啊。这么基础的东西一定有很多应用前景吧!(心虚)
Subset Sum 问题单个物品重量限制前提下的更优算法的更多相关文章
- Subset sum problem
https://en.wikipedia.org/wiki/Subset_sum_problem In computer science, the subset sum problem is an i ...
- 动态规划法(三)子集和问题(Subset sum problem)
继续讲故事~~ 上次讲到我们的主人公丁丁,用神奇的动态规划法解决了杂货店老板的两个找零钱问题,得到了老板的肯定.之后,他就决心去大城市闯荡了,看一看外面更大的世界. 这天,丁丁刚回到家,他 ...
- Partition Equal Subset Sum
Given a non-empty array containing only positive integers, find if the array can be partitioned into ...
- LN : leetcode 416 Partition Equal Subset Sum
lc 416 Partition Equal Subset Sum 416 Partition Equal Subset Sum Given a non-empty array containing ...
- Light OJ 1272 Maximum Subset Sum 高斯消元 最大XOR值
版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u011686226/article/details/32337735 题目来源:problem=12 ...
- call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法.
call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法. 注意:该函数的语法与 apply() 方法的语法几乎完全相同,唯一的区别在于,apply()方法接受的是一个参 ...
- 如何使用python在保留原excel格式的前提下插入/修改数据
一.需求分析: 统计的报表中需要每日查询当天数据并追加到原有的excel后面. 因为原始excel格式已经设定好,如果使用xlwt,仅仅指定设定我们要插入的单元格的格式,原始数据的格式会被初始化. 所 ...
- a,b,c为3个整型变量,在不引入第四个变量的前提下写一个算法实现 a=b b=c c=a?(异或解决值互换问题)
package com.Summer_0424.cn; /** * @author Summer * a,b,c为3个整型变量,在不引入第四个变量的前提下写一个算法实现 a=b b=c c=a? */ ...
- a,b为2个整型变量,在不引入第三个变量的前提下写一个算法实现 a与b的值互换
package com.Summer_0424.cn; /** * @author Summer * a,b为2个整型变量,在不引入第三个变量的前提下写一个算法实现 a与b的值互换? */ publi ...
- 不修改模板的前提下修改VisualState中的某些值
原文链接:不修改模板的前提下修改VisualState中的某些值 - 超威蓝火 UWP里有一件非常令人不爽的事,大部分控件只提供了Normal状态下的Background,Foreground,Bor ...
随机推荐
- nginx重启和操作
在linux操作系统中,重启nginx 1.当不知道nginx所在目录时,需要先查找到nginx的位置 查看ngnix位置(master process 后面的就是 nginx的目录): ps -e ...
- 高可用(keepalived)部署方案
前言:为了减少三维数据中心可视化管理系统的停工时间,保持其服务的高度可用性.同时部署多套同样的三维可视化系统,让三维数据中心可视化系统同时部署并运行到多个服务器上.同时提供一个虚拟IP,然后外面通过这 ...
- devops工具链基建建设评价标准
之所以写这篇是因为有朋友私下让我完善下基建建设的标准和四个阶梯划分,然后让我一定要把腾讯和百度加到基建建设的排名中(看热闹不嫌事大). 基建infra建设四个考察维度 1)工具链完整性:该有的工具是否 ...
- 用 hexo 结合 github 从0到1开始搭建属于你的blog
前言 github pages服务搭建博客的好处有: 全是静态文件,访问速度快: 免费方便,不用花一分钱就可以搭建一个自由的个人博客,不需要服务器不需要后台: 可以随意绑定自己的域名,不仔细看的话根本 ...
- 从Chat-GPT看爆火技术概念及医疗领域科技与应用场景
作者:京东健康 陈刚 一.前言 最近OpenAI在官网上宣告了多模态大模型 GPT-4 的诞生,它可能是迄今为止最好的多模态模型. 主要更新内容如下: 1. 逻辑分析能力更加全面.「考试」能力大幅提升 ...
- Rust中的Copy和Clone
1.Copy和Clone Rust中的Copy和Clonetrait都允许创建类型实例的副本.它们都提供了一种复制类型实例的方法,但它们之间存在一些重要的区别.了解这些区别有助更好地使用这两个特征. ...
- Java全栈开发/API
2023/4/16 记录我学习的网站 前端 vuejs axios异步请求 微信开发者文档 uniapp开发文档 快速参考备忘清单 免费前端接口 读取json vant4UI cubeUI mintU ...
- C# 反射 判断类型是否是列表
1 /// <summary> 2 /// 判断类型是否为可操作的列表类型 3 /// </summary> 4 /// <param name="type&q ...
- 再解 [NOI2017] 整数
提供一个来自 CF 大佬 adament 的有趣思路. 首先我们知道的是一个只增加的 \(b\) 进制整数计数器,如果 \(b\) 是常数那么复杂度是均摊 \(O(1)\) 的.证明只需要考虑将 \( ...
- 2021-08-04:给定一个字符串str,当然可以生成很多子序列。返回有多少个子序列是回文子序列,空序列不算回文。比如,str = “aba”,回文子序列:{a}、{a}、 {a,a}、 {b}、{
2021-08-04:给定一个字符串str,当然可以生成很多子序列.返回有多少个子序列是回文子序列,空序列不算回文.比如,str = "aba",回文子序列:{a}.{a}. {a ...