前言

看了 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\)。转移如下:

\[\begin{cases}
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 问题单个物品重量限制前提下的更优算法的更多相关文章

  1. Subset sum problem

    https://en.wikipedia.org/wiki/Subset_sum_problem In computer science, the subset sum problem is an i ...

  2. 动态规划法(三)子集和问题(Subset sum problem)

      继续讲故事~~   上次讲到我们的主人公丁丁,用神奇的动态规划法解决了杂货店老板的两个找零钱问题,得到了老板的肯定.之后,他就决心去大城市闯荡了,看一看外面更大的世界.   这天,丁丁刚回到家,他 ...

  3. Partition Equal Subset Sum

    Given a non-empty array containing only positive integers, find if the array can be partitioned into ...

  4. LN : leetcode 416 Partition Equal Subset Sum

    lc 416 Partition Equal Subset Sum 416 Partition Equal Subset Sum Given a non-empty array containing ...

  5. Light OJ 1272 Maximum Subset Sum 高斯消元 最大XOR值

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/u011686226/article/details/32337735 题目来源:problem=12 ...

  6. call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法.

    call 方法在使用一个指定的this值和若干个指定的参数值的前提下调用某个函数或方法. 注意:该函数的语法与 apply() 方法的语法几乎完全相同,唯一的区别在于,apply()方法接受的是一个参 ...

  7. 如何使用python在保留原excel格式的前提下插入/修改数据

    一.需求分析: 统计的报表中需要每日查询当天数据并追加到原有的excel后面. 因为原始excel格式已经设定好,如果使用xlwt,仅仅指定设定我们要插入的单元格的格式,原始数据的格式会被初始化. 所 ...

  8. 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? */ ...

  9. a,b为2个整型变量,在不引入第三个变量的前提下写一个算法实现 a与b的值互换

    package com.Summer_0424.cn; /** * @author Summer * a,b为2个整型变量,在不引入第三个变量的前提下写一个算法实现 a与b的值互换? */ publi ...

  10. 不修改模板的前提下修改VisualState中的某些值

    原文链接:不修改模板的前提下修改VisualState中的某些值 - 超威蓝火 UWP里有一件非常令人不爽的事,大部分控件只提供了Normal状态下的Background,Foreground,Bor ...

随机推荐

  1. 浅学git工具

    1.git工具介绍及使用 git工具直接安装: 直接运行exe文件进行安装,按默认的操作点击下一步就行了 校验: 在DOS命令行中输入:git  --version 如果能正常显示出对应的版本就是ok ...

  2. 逍遥自在学C语言 | 变量、常量与数据类型

    前言 一.人物简介 第一位闪亮登场,有请今后会一直教我们C语言的老师 -- 自在. 第二位上场的是和我们一起学习的小白程序猿 -- 逍遥. 二.基本数据类型 1.整型 C语言中的整型数据如下表所示: ...

  3. Laplace分布算子开发经验分享

    摘要:Laplace 用于 Laplace 分布的概率统计与随机采样. 本文分享自华为云社区<Laplace分布算子开发经验分享>,作者:李长安. 1.任务解析 详细描述: Laplace ...

  4. [网络]内网IP的判别与分类

    1 内网IP划分 内网IP地址分为A类.B类和C类,其地址范围如下: A类地址: 10.0.0.0 - 10.255.255.255 B类地址: 172.16.0.0 - 172.31.255.255 ...

  5. Java设计模式 —— 工厂模式

    3 简单工厂模式 3.1 创建型模式 Creational Pattern 关注对象的创建过程,对类的实例化过程进行了抽象,将软件模块中对象的创建和对象的使用分离,对用户隐藏了类的实例的创建细节.创建 ...

  6. 访问不到tomcat下的静态资源文件

    问题:idea+tomcat 测试Servlet,居然访问不到与WEB-INF同级的静态资源1.html.又不是访问WEB-INF里的文件.... 分析:可能是开发目录中的文件没有自动复制到部署目录. ...

  7. python:模拟购票的小程序

    问题描述:小白学习python的第N天,继续练习.做一个模拟购票的小程序,没有用数据库和文件来存储数据,只是能够单词选择. # hzh 每天进步一点点 # 2022/5/13 17:24 import ...

  8. CSS实现段落首行缩进两个字符

    段落前面空两个字的距离,不要再使用空格了,对于文字,需要使用4个 才会显示汉字2个字符空格的效果. 用CSS实现段落首缩进两个字符,应该使用首行缩进text-indent.text-indent可以使 ...

  9. Swift CustomStringConvertible 协议的使用

    目录 一.前言 二.使用场景 1. 整型类型的枚举使用 2. Class类型的使用 一.前言 先看一下Swift标准库中对CustomStringConvertible协议的定义 public pro ...

  10. 从原理聊JVM(三):详解现代垃圾回收器Shenandoah和ZGC

    作者:京东科技 康志兴 Shenandoah Shenandoah一词来自于印第安语,十九世纪四十年代有一首著名的航海歌曲在水手中广为流传,讲述一位年轻富商爱上印第安酋长Shenandoah的女儿的故 ...