背包,子集和以及 (max, +) 卷积在特殊情形下的求法

子集和 1:总重量不太大

有 \(n\) 个物品,每个物品重量为 \(w_i\),且 \(\sum\limits_{i} w_i=C\)。你需要对于 \(k\in [1,C]\) 均求出是否存在子集和 \(=k\)。

时间复杂度 \(\mathcal O(\frac{C\sqrt{C}}{\omega})\),空间复杂度 \(\mathcal O(n+\frac{C}{\omega})\)。

我们对于相同重量的物品二进制分组,然后暴力 01 背包,用 bitset 加速即可。

时间复杂度证明:

不妨设重量为 \(w\) 的物品有 \(a\) 个,则 \(\sum\limits_{i=1}^{m} w_ia_i=C\)。二进制拆分后的物品数为 \(\sum\limits_{k=0}\sum\limits_{i=1}^{m} [a_i\ge 2^k]\)。

对于固定的 \(k\),满足 \([a_i\ge 2^k]\) 的 \(i\) 有 \(\sqrt{\frac{C}{2^k}}\) 个,因此物品数 \(\sum\limits_{k}\sqrt{\frac{C}{2^k}}=\sqrt{C}\sum\limits_{k}2^{-k/2}\le \frac{\sqrt{2}}{\sqrt{2}-1}\sqrt{C}\)。


子集和 2:单个重量不太大

有 \(n\) 个物品,每个物品重量为 \(w_i\),满足 \(w_i\le D\)。问是否存在子集和 \(=C\)。

时间复杂度 \(\mathcal O(nD)\),空间复杂度 \(\mathcal O(n+D)\)时间复杂度 \(\mathcal O(\frac{n\sqrt{n}D}{\omega})\),空间复杂度 \(\mathcal O(n+\frac{\sqrt{n}D}{\omega})\)

法一:

先找到最大的 \(k\) 满足 \(\sum\limits_{i=1}^{k} w_i\le C\),问题转化为能否从 \(\{-w_1,\cdots,-w_k,w_{k+1},\cdots,w_n\}\) 选出子集和 \(C-\sum\limits_{i=1}^{k}w_i\)。该做法的核心思想是:如果当前子集和 \(>C\),那么从 \(w_1\sim w_k\) 中选一些数减到 \(\le C\),否则从 \(w_{k+1}\sim w_n\) 中选一些数加到 \(>C\)。

我们定义 \(\text{can}(tot,l,r)\) 表示是否存在 \(\lambda_{l},\lambda_{l+1},\cdots,\lambda_{r}=\{0,1\}\) 满足 \(\sum\limits_{i=1}^{l-1}w_i+\sum\limits_{i=l}^{r} \lambda_iw_i=tot\)。

性质 1:固定 \(tot,r\),则 \(\text{can}(tot,l,r)=1\) 的 \(l\) 为一段前缀。

我们定义 \(dp_{tot,r}\) 表示最大的 \(l\) 满足 \(\text{can}(tot,l,r)=1\)(如不存在,\(dp=-1\))。考虑转移。

性质 2:固定 \(tot,l\),则 \(\text{can}(tot,l,r)=1\) 的 \(r\) 为一段后缀。

据此有 \(dp_{tot,r}\le dp_{tot,r+1}\),于是有三类转移:

  • \(dp_{tot+w_{r+1},r+1}\leftarrow dp_{tot,r}\)
  • \(dp_{tot,r+1}\leftarrow dp_{tot,r}\)
  • \(dp_{tot-w_{l'},r}\leftarrow l'\ (l'\in [1,dp_{tot,r}))\)

我们发现第三类转移有 \(\mathcal O(n)\) 条,但是对于固定的 \(tot\),我们在 \(dp_{tot,r}\) 时有意义的转移只有 \(l'\in [dp_{tot,r-1},dp_{tot,r})\),否则可以在 \(dp_{tot,r-1}\) 的时候就转移掉。

因此,对于固定的 \(tot\),第三类转移总共有 \(\mathcal O(n)\) 条,因此时间复杂度是均摊 \(\mathcal O(nD)\) 的。

法二:

考虑随机打乱这个集合,则过程中期望达到的最值为 \(\mathcal O(\sqrt{n}D)\),用 bitset 加速即可。


(max, +) 卷积

给定两个长为 \(n\) 的序列 \(A,B\),求它们的 \((max,+)\) 卷积 \(C\)。保证 \(B\) 是凸函数。

时间复杂度 \(\mathcal O(n\log n)\) 或 \(\mathcal O(n)\),空间复杂度 \(\mathcal O(n)\)。

法一:

我们记 \(C_i\) 的决策位置(即 \(B\) 序列位置)为 \(f_i\),容易证明 \(f_{i-1}\le f_i\)。因此直接分治即可。

时间复杂度 \(\mathcal O(n\log n)\),空间复杂度 \(\mathcal O(n)\)。

法二:

考虑构建一个 \((2n-1)\times n\) 的矩阵 \(X\),满足 \(X_{i,j}=A_i+B_{i-j}\)。我们想要的即为 \(X\) 的每行最小值。

由于 \(B\) 是凸的,所以 \(X\) 是完全单调矩阵,用 SMAWK 求解即可。

不过听 Froggy 说 SMAWK 的效率被二分栈 / 分治吊打,所以可能 not practical。

时间复杂度 \(\mathcal O(n)\),空间复杂度 \(\mathcal O(n)\)。


01 背包:单个重量不太大

有 \(n\) 个物品,每个物品重量为 \(w_i\),价值为 \(v_i\),不同的 \(w_i\) 有 \(D\) 个。选出最大的子集 \(S\) 满足重量和不超过 \(C\),且总价值最大。

时间复杂度 \(\mathcal O(n\log n+DC\log C)\) 或 \(\mathcal O(n\log n+DC)\),空间复杂度 \(\mathcal O(n+C)\)。

对于相同 \(w\) 的物品,我们肯定将 \(v\) 从大到小贪心取,图像为一个凸函数。因此我们将背包在模 \(C\) 意义下分别做 \((max,+)\) 卷积即可。


完全背包:单个重量不太大

有 \(n\) 个物品,每个物品重量为 \(w_i\),价值为 \(v_i\),满足 \(w_i\le D\)。选出最大的可重子集 \(S\) 满足重量和不超过 \(C\),且总价值最大。

时间复杂度 \(\mathcal O(D^2\log C)\),空间复杂度 \(\mathcal O(n+D)\)。

注意到对于 \(i>D\),有 \(dp_i=\max\limits_{j+k=i} (dp_j+dp_k)\),且如果 \(|j-k|>D\),我们始终可以调整得到 \(|j-k|\le D\)。

因此通过 \([dp_{j-\frac{D}{2}},\cdots,dp_{j+\frac{D}{2}}]\) 以及 \([dp_{k-\frac{D}{2}},\cdots,dp_{k+\frac{D}{2}}]\),可以暴力卷积得到 \(dp_{j+k}\) 的值。

现在,假如我们知道了 \([dp_{k-D},\cdots,dp_{k+D}]\),它卷自己可以得到 \([dp_{2k-D},\cdots,dp_{2k+D}]\)。因此采用倍增的形式可以快速计算出 \([dp_{C-D},\cdots,dp_{C}]\),答案即为其中的最大值。

初始化的地方,暴力计算 \([dp_0,\cdots,dp_{2D}]\) 即可。

背包,子集和以及 (max, +) 卷积在特殊情形下的求法的更多相关文章

  1. 直接抱过来dd大牛的《背包九讲》来做笔记

    P01: 01背包问题 题目 有N件物品和一个容量为V的背包.第i件物品的费用是c[i],价值是w[i].求解将哪些物品装入背包可使这些物品的费用总和不超过背包容量,且价值总和最大. 基本思路 这是最 ...

  2. HDU 3535 AreYouBusy (混合背包)

    题意:给你n组物品和自己有的价值s,每组有l个物品和有一种类型: 0:此组中最少选择一个 1:此组中最多选择一个 2:此组随便选 每种物品有两个值:是需要价值ci,可获得乐趣gi 问在满足条件的情况下 ...

  3. UESTC 424 AreYouBusy --混合背包

    混合三种背包问题. 定义:dp[i][k]表示体积为k的时候,在前i堆里拿到的最大价值. 第一类,至少选一项,dp初值全赋为负无穷,这样才能保证不会出现都不选的情况.dp[i][k] = max(dp ...

  4. Uva 12563,劲歌金曲,01背包

    题目链接:https://uva.onlinejudge.org/external/125/12563.pdf 题意:n首歌,每首歌的长度给出,还剩 t 秒钟,由于KTV不会在一首歌没有唱完的情况下切 ...

  5. HDU 5234 Happy birthday --- 三维01背包

    HDU 5234 题目大意:给定n,m,k,以及n*m(n行m列)个数,k为背包容量,从(1,1)开始只能往下走或往右走,求到达(m,n)时能获得的最大价值 解题思路:dp[i][j][k]表示在位置 ...

  6. 卷积神经网络CNN全面解析

    卷积神经网络(CNN)概述 从多层感知器(MLP)说起 感知器 多层感知器 输入层-隐层 隐层-输出层 Back Propagation 存在的问题 从MLP到CNN CNN的前世今生 CNN的预测过 ...

  7. uva 11825 Hackers' Crackdown (状压dp,子集枚举)

    题目链接:uva 11825 题意: 你是一个黑客,侵入了n台计算机(每台计算机有同样的n种服务),对每台计算机,你能够选择终止一项服务,则他与其相邻的这项服务都终止.你的目标是让很多其它的服务瘫痪( ...

  8. 第十三章——卷积神经网络(CNN)

    卷积神经网络(Convolutional neural networks,CNNs)来源于对大脑视觉皮层的研究,并于1980s开始应用于图像识别.现如今CNN已经在复杂的视觉任务中取得了巨大成功,比如 ...

  9. HDU 2602 Bone Collector 骨头收集者【01背包】

    题目链接:https://vjudge.net/contest/103424#problem/A 题目大意: 第一行输入几组数据,第二行第一个数字代表物体个数,第二个数代表总体积.需要注意的是,第三排 ...

随机推荐

  1. 【Python打包成exe方法】——已解决导入第三方包无法打包的问题

    ​ 前言 在我们写代码的过程中,我们开发的脚本一般都会用到一些第三方包,可能别人也需要用到我们的脚本,如果我们将我们的xx.py文件发给他,他是不能直接用的,他还需要安装python解释器,甚至还要安 ...

  2. linux(Ubuntu)安装python

    Linux下安装python 提前安装一个依赖环境 (1)ubuntu/Debian: sudo apt-get install -y gcc make cmake build-essential l ...

  3. Python入门-字符串格式化

    一.不推荐使用:%号 #正常按照位置传递参数 print('%s asked %s to do something' % ('egon', 'lili')) #先后顺序不能乱 #字典传递参数 prin ...

  4. sourceCRT设置全局字符集为utf-8

    以前刚打开服务器crt字符集都会默认是default模式,搞得每次都要手动设置成UTF-8. 烦躁. 将CRT全局字符集设置成UTF-8格式方法: 设置窗口不会断掉: 即每100s发送一次ls \n ...

  5. shell、bash和sh区别

    shell是你(用户)和Linux(或者更准确的说,是你和Linux内核)之间的接口程序.你在提示符下输入的每个命令都由shell先解释然后传给Linux内核. shell 是一个命令语言解释器(co ...

  6. 百兆以太网(100BASE-TX)的波形和眼图

    沾了公司的光用了那台采样率吓死人的示波器看了下百兆以太网的三电平波形和眼图. 之前我也强调过百兆的三电平是不能从1状态越过0状态跳到-1状态的,从眼图上能明显看出来. 可以看出这个信号还是不错的.甚至 ...

  7. 2021-01-25 cf #697 Div3 C题(超时,换思路减少复杂度)

    题目链接:https://codeforces.com/contest/1475/problem/C 题意要求:需组成的2对,男的序号不能重,女的序号不能重 比如这例 输入: 行1--测试个数 行1` ...

  8. acwing刷题-放养又没有完全放养

    题目 一个鲜为人知的事实是,奶牛拥有自己的文字:「牛文」. 牛文由 26 个字母 a 到 z 组成,但是当奶牛说牛文时,可能与我们所熟悉的 abcdefghijklmnopqrstuvwxyz 不同, ...

  9. Dockerfile 命令详解及最佳实践

    Dockerfile 命令详解 FROM 指定基础镜像(必选) 所谓定制镜像,那一定是以一个镜像为基础,在其上进行定制.就像我们之前运行了一个 nginx 镜像的容器,再进行修改一样,基础镜像是必须指 ...

  10. java第十二周作业

    1.定义一个点类Point, 包含2个成员变量x.y分别表示x和y坐标,2个构造器Point()和Point( intx0,y0),以及一个movePoint (int dx,intdy)方法实现点的 ...