博客园同步

前置知识:

  • 浅谈单调队列
  • 简单背包问题

这篇文章我们主要研究 单调队列优化 dp\text{dp}dp 如何用于背包问题部分特殊背包问题的优化方式

01\text{01}01 背包问题

nnn 个物品,背包体积为 VVV,每个物品有 viv_ivi​(价值)和 wiw_iwi​(重量),每个物品只有 111 个。求在不超过背包体积的情况下能获得的最大价值。
n,V,vi,wi≤1×103n,V,v_i,w_i \leq 1 \times 10^3n,V,vi​,wi​≤1×103,时间限制 1s1s1s,空间限制 16MB16MB16MB.

简单的考虑,用 fi,jf_{i,j}fi,j​ 表示前 iii 个物品,背包体积为 jjj 的答案,则易得:

fi,j=max⁡(fi−1,j,fi−1,j−wi+vi)f_{i,j} = \max(f_{i-1,j} , f_{i-1 , j-w_i} + v_i)fi,j​=max(fi−1,j​,fi−1,j−wi​​+vi​)

这样可以在 O(nV)\mathcal{O}(nV)O(nV) 的时间内解决问题。

但是你发现空间只有 16MB16 \text{MB}16MB,由于 iii 的决策只取决于上一行同一列,所以可以直接降维,得:

fj=max⁡(fj,fj−wi+vi)f_j = \max(f_j , f_{j-w_i} + v_i)fj​=max(fj​,fj−wi​​+vi​)

注意 j≥wij \geq w_ij≥wi​ 的隐约限制。

伪代码如下:

for (i=1;i<=n;i++)
for (j=V;j>=w[i];j--)f[j] = max(f[j] , f[j-w[i]] + v[i]);

O(nV)\mathcal{O}(nV)O(nV) 是最优的算法。今天我们所要实现的,仅仅是,把所有的背包算法复杂度都降为 O(nV)\mathcal{O}(nV)O(nV).

倒叙枚举 - 小细节

你可能会在代码里注意到一行:

for (j=V;j>=w[i];j--)

为什么是倒序枚举呢?它和

for(j=w[i];j<=V;j++)

等价吗?

这是一个初学者常常犯的错误,这两种写法并不等价。可以运用这种写法去解决完全背包。

如果你是正序枚举的话,你会发现,iii 号物品会被重复使用很多次。比方说 wi=2,vi=3w_i = 2 , v_i = 3wi​=2,vi​=3 时,那么 j=4j=4j=4 就会从 j=2j=2j=2 转移过来,此时 程序已经把 iii 物品用了 222 次,这样是不可取的。而反之在完全背包中则是可取的,因为完全背包问题是 无限个数 ,可以这样写。

当然如果你倒序枚举的话,此时对于所有 j=wi,j=2×wi⋯⋯j = w_i , j = 2 \times w_i \cdots \cdotsj=wi​,j=2×wi​⋯⋯ 中,就只会更新 j=wij=w_ij=wi​ 的,因为倒序的时候 jjj 从 j−wij-w_ij−wi​ 来,前一个还没有推出来就推导后一个,肯定没有答案——这样正好是我们所求的。而 j=wij=w_ij=wi​ 有答案的原因就是因为本身的一次更新。

之后遇到的各种 dp\text{dp}dp 都会出现类似此类的问题,大家一定要小心!

完全背包问题

nnn 个物品,背包体积为 VVV,每个物品有 viv_ivi​(价值)和 wiw_iwi​(重量),每个物品有无限个。求在不超过背包体积的情况下能获得的最大价值。
n,V,vi,wi≤1×103n,V,v_i,w_i \leq 1 \times 10^3n,V,vi​,wi​≤1×103,时间限制 1s1s1s,空间限制 16MB16MB16MB.

这样你会发现一个问题,你不知道有多少个!

当然你可以用 ⌊Vvi⌋\lfloor \frac{V}{v_i} \rfloor⌊vi​V​⌋ 来表示数量,考虑枚举。

同样的 fi,jf_{i,j}fi,j​,我们可以知道:

fi,j=max⁡k=0⌊Vvi⌋(fi−1,j−k×wi+k×vi)f_{i,j} = \max_{k=0}^{\lfloor \frac{V}{v_i} \rfloor}(f_{i-1,j-k \times w_i} + k \times v_i)fi,j​=k=0max⌊vi​V​⌋​(fi−1,j−k×wi​​+k×vi​)

大前提是 j≥k×wij \geq k \times w_ij≥k×wi​,这样转移的复杂度是 O(nVwi)\mathcal{O}(nVw_i)O(nVwi​),降维之后应该可以通过。

考虑一个简单的加强:

n,V,vi,wi≤1×104n,V,v_i,w_i \leq 1 \times 10^4n,V,vi​,wi​≤1×104,空间限制 128MB128MB128MB.

我们将在下面的研究中,解决这个问题。

多重背包问题

nnn 个物品,背包体积为 VVV,每个物品有 viv_ivi​(价值)和 wiw_iwi​(重量),每个物品有 numi\text{num}_inumi​ 个。求在不超过背包体积的情况下能获得的最大价值。
n,V,vi,wi≤1×104n,V,v_i,w_i \leq 1 \times 10^4n,V,vi​,wi​≤1×104,时间限制 1s1s1s,空间限制 128MB128MB128MB.

显然我们按照完全背包的方法就可以了,但是 O(nVwi)\mathcal{O}(nVw_i)O(nVwi​) 是不可能通过 10410^4104 的!所以我们需要考虑,如何优化这个问题。

实际上不用单调队列也可以优化,我们先来讲著名的背包优化的几个方法。

二进制拆分

二进制!这是个熟悉的东西。

实际上我们背包的瓶颈在于两个:背包物品过多,背包容积过大,背包物品数量过多。

容积过大可能会想到离散,但是这不是排序之类只用知道大小的问题啊!容积是不能突破的,考虑优化物品个数。物品个数怎么可能优化呢?数量?

那你可能会说,这和二进制又有什么关系?

下面我们来说一说吧。

用二进制表示数

用集合 sss 表示二的幂次集,则 s={20,21⋯2∞}s = \{ 2^0 , 2^1 \cdots 2^{\infty}\}s={20,21⋯2∞}.每个正整数都可以用若干个 sss 集合内的元素相加而成。就是说每个数一定能被分解成若干二的幂次的数之和。

10=2+810 = 2 +810=2+8
100=64+32+4100 = 64 + 32 +4100=64+32+4
1000=512+256+128+64+32+81000 = 512 + 256 + 128 + 64 + 32 + 81000=512+256+128+64+32+8

如何证明?

显而易见,每个数都能被二进制表示。比方说 1010=1001210_{10} = 1001_21010​=10012​.

那么,用计数原则,10012=1×20+0×21+0×22+1×231001_2 = 1 \times 2^0 + 0 \times 2^1 + 0 \times 2^2 + 1 \times 2^310012​=1×20+0×21+0×22+1×23

这样就证明结束了,你没有发现吗?

拆分原理

将一个 {vi,wi,numi}\{ v_i , w_i , num_i\}{vi​,wi​,numi​} 的物品,通过 numinum_inumi​ 进行拆分。

本来假设一个物品有 777 个,你可以把它拆开成 1,2,41,2,41,2,4 个,对这三个物品进行 010101 背包,你就可以得到 1−71 - 71−7 所有可能的答案。最后你把不取的答案单独做一遍就可以了。

原理就是, nnn 最多被拆成 log⁡n\log nlogn 个二的幂次的数之和,这样保证了时间复杂度是 O(nVlog⁡wi)\mathcal{O}(nV \log w_i)O(nVlogwi​) 的。

伪代码
for(i=1;i<=n;i++) {read(x) , read(y) , read(z);for(j=1;j<=z;j<<=1) v[++cnt]=x*j,w[cnt]=y*j,z-=j;if(z) v[++cnt]=x*z,w[cnt]=y*z;
}
// use array v and w to do 01 backpack

单调队列

显然,10410^4104 的数据可以把二进制拆分卡死。我们需要严格去掉 log⁡\loglog.

再看一眼这个状态转移:

fi,j=max⁡k=0numi(fi−1,j−k×wi+k×vi)f_{i,j} = \max_{k=0}^{\text{num}_i}(f_{i-1,j-k \times w_i} + k \times v_i)fi,j​=k=0maxnumi​​(fi−1,j−k×wi​​+k×vi​)

你会发现,这不是一段连续的决策!这是断续的。

但是,你会发现这样一个问题。

fi−1,j,fi−1,j−wi,fi−1,j−2×wi⋯fi−1,j−numi×wif_{i-1 , j} , f_{i-1 , j - w_i} , f_{i-1 , j - 2 \times w_i} \cdots f_{i-1 , j - \text{num}_i \times w_i}fi−1,j​,fi−1,j−wi​​,fi−1,j−2×wi​​⋯fi−1,j−numi​×wi​​,这是所有 fi,jf_{i,j}fi,j​ 的决策点。

你会发现,这些决策点是同行等差列的,每两个决策点隔着一个 wiw_iwi​. 这非常好!

余数构造连续决策

你会发现,你可以把 VVV 按照模 wiw_iwi​ 进行分类,余数相同的肯定是一类的。

那样我们就可以把这一段当成连续的决策去做,因为实际上枚举余数 mo\text{mo}mo 和当前周期编号 kkk. 因为 kkk 是连续的,那么 mo+k×wi\text{mo} + k \times w_imo+k×wi​ 实际上就是当前的决策点。这样我们构造出了若干段连续的决策。

时间复杂度分析

对 nnn 个物品每次做一次,所以 O(n)\mathcal{O}(n)O(n).

然后同时枚举余数和 kkk,因为 mo×k≤V\text{mo} \times k \leq Vmo×k≤V,所以本质上这两重循环的 ∑\sum∑ 不会超过 VVV,是 O(V)\mathcal{O}(V)O(V).

按照单调队列每个节点进出一次的原理,O(nV)\mathcal{O}(nV)O(nV) 的目标已然达成。

for(i=1;i<=n;i++) {read(v) , read(w) , read(num); num=min(num,V/v);for(mo=0;mo<v;mo++) {l=r=0;for(k=0;k<=(V-mo)/v;k++) {x=k,y=f[k*v+mo]-k*w;while(l<r && q[l].pos<k-num) l++;while(l<r && q[r-1].val<=y) r--;q[r].val=y,q[r++].pos=x;f[k*v+mo]=q[l].val+k*w;}}}

完全背包问题 - 单调队列

这里我们发现,直接把 ⌊Vvi⌋\lfloor \frac{V}{v_i} \rfloor⌊vi​V​⌋ 作为 num\text{num}num 就可以直接通过。这样我们实现了完全背包和多重背包的 O(nV)\mathcal{O}(nV)O(nV).

下面,有了多重背包和完全背包的基础,我们将来解决更套路性的问题。

混合背包问题

nnn 个物品,背包体积为 VVV,每个物品有 viv_ivi​(价值)和 wiw_iwi​(重量),每个物品的个数用符号 ttt 表示。t=−1t=-1t=−1 表示该物品只有 111 个,t=0t=0t=0 表示该物品有无限个,t>0t>0t>0 表示该物品有 ttt 个。求在不超过背包体积的情况下能获得的最大价值。
n,V,vi,wi≤1×104n,V,v_i,w_i \leq 1 \times 10^4n,V,vi​,wi​≤1×104,时间限制 1s1s1s,空间限制 128MB128MB128MB.

很显然,我们可以把 010101 背包的物品看成是 numi=1\text{num}_i = 1numi​=1 的多重背包物品,完全背包的物品看成是 numi=⌊Vvi⌋\text{num}_i = \lfloor \frac{V}{v_i} \rfloornumi​=⌊vi​V​⌋ 的多重背包物品,最后用 O(nV)\mathcal{O}(nV)O(nV) 跑一遍多重背包即可。

代码略。

二维费用背包问题

nnn 个物品,背包体积为 VVV,所能承受的最大重量为 WWW.每个物品有 viv_ivi​(价值)和 wiw_iwi​(重量)和 gig_igi​(体积)。求在不超过背包体积 且 不超过最大载重的情况下能获得的最大价值。(每个物品只有 111 个)
n,V,vi,wi≤5×102n,V,v_i,w_i \leq 5 \times 10^2n,V,vi​,wi​≤5×102,时间限制 1s1s1s,空间限制 128MB128MB128MB.

显然,我们出现了另一层限制,使得我们无法用 O(nV)\mathcal{O}(nV)O(nV) 的时间解决。实际上时间限制也暗示了这一点。我们应该从头开始,重新推导。其实大多过程是类似的。

基础推导过程

用 fi,j,kf_{i,j,k}fi,j,k​ 表示前 iii 个物品,体积为 jjj,载重为 kkk 的最大价值。

那么可得:

fi,j,k=max⁡(fi−1,j,k,fi−1,j−gi,k−wi+vi)f_{i,j,k} = \max(f_{i-1,j,k} , f_{i-1,j-g_i , k - w_i} + v_i)fi,j,k​=max(fi−1,j,k​,fi−1,j−gi​,k−wi​​+vi​)

按照这个方式,O(nVW)\mathcal{O}(nVW)O(nVW) 足以解决 5×1025 \times 10^25×102 的数据。

伪代码如下:

for(i=1;i<=n;i++) {read(g) , read(w) , read(v);for(j=V;j>=g;j--)for(k=W;k>=w;k--)f[j][k]=max(f[j][k],f[j-g][k-w]+v); //降维同 01 背包操作
}

拓展二维背包问题

假设,每个物品有 numi\text{num}_inumi​ 个,其余按照二维背包条件不变,5×1025 \times 10^25×102 仍不变,如何追求一个 O(nVW)\mathcal{O}(nVW)O(nVW) 的算法?

实际上单调队列仅仅是让我们 完全地把背包的复杂度寄托于物品的个数与限制条件,而与具体数值大小无关,所以单调队列是可以做到的。

fi,j,k=max⁡l=0numi(fi−1,j−l×wi,k−l×gi+l×vi)f_{i,j,k} = \max_{l=0}^{\text{num}_i} (f_{i-1,j-l \times w_i , k-l \times g_i} + l \times v_i)fi,j,k​=l=0maxnumi​​(fi−1,j−l×wi​,k−l×gi​​+l×vi​)

但是,这个你和一维的背包问题比较一下呢:

fi,j=max⁡k=0numi(fi−1,j−k×wi+k×vi)f_{i,j} = \max_{k=0}^{\text{num}_i}(f_{i-1,j-k \times w_i} + k \times v_i)fi,j​=k=0maxnumi​​(fi−1,j−k×wi​​+k×vi​)

一维背包的周期是 wiw_iwi​.按照这个说法,二维背包的周期应该是 lcm⁡(wi,gi)\operatorname{lcm}(w_i , g_i)lcm(wi​,gi​),可以认为是 wi×giw_i \times g_iwi​×gi​.

我们需要同时枚举两个模数 mo1\text{mo1}mo1 和 mo2\text{mo2}mo2,用 mo1×wi+mo2\text{mo1} \times w_i + \text{mo2}mo1×wi​+mo2 来表示当前节点,然后用单调队列做即可。

时间复杂度仍然是 O(nVW)\mathcal{O}(nVW)O(nVW),一个道理,每个节点入队出队一次。

但是严格意义上这个做法是不对的。为什么呢?

拓展多维背包问题

在拓展二维的基础上,把每个物品的限制加到 kkk 个,能否做到 O(nVW)\mathcal{O}(nVW)O(nVW)?答案是不能。O(nVWk)\mathcal{O}(nVWk)O(nVWk)?这当然可以。

这样对于 kkk 个限制的相乘,单调队列的优化已经基本无用。因为在完全随机的,k≥3k \geq 3k≥3 的情况之下,kkk 个数的乘积很容易就超过了 max⁡i=1nwi\max_{i=1}^n w_imaxi=1n​wi​ 使得优化失败,无法进行单调队列操作。

所以,222 维也是一个道理,两个随机的 ≤5×102\leq 5 \times 10^2≤5×102 的数相乘超过 5×1025 \times 10^25×102 的概率很大。一旦出现这样的物品,我们的单调队列等同于大暴力。而大暴力的复杂度恰恰是 O(nVWk)\mathcal{O}(nVWk)O(nVWk),对于 kkk 个限制还需要进行循环判断,常数较大。

所以,一般的题目会给定 kkk 的值(并且一般来说 k≤3k \leq 3k≤3),把 kkk 当做常数来看!

分组背包问题

nnn 个物品,背包体积为 VVV.每个物品有 viv_ivi​(价值)和 wiw_iwi​(重量),只有 111 个。
每个物品属于第 sis_isi​ 组。求不超过背包体积 且 每组只选一个物品的最大价值。
n,V,vi,wi≤1×103n,V,v_i,w_i \leq 1 \times 10^3n,V,vi​,wi​≤1×103,时间限制 1s1s1s,空间限制 128MB128MB128MB.

很明显,我们应该考虑 dp\text{dp}dp 的推导。用 fk,jf_{k,j}fk,j​ 表示前 kkk 组物品重量为 jjj 所得的最大价值,易得:

fk,j=max⁡(fk−1,j,max⁡si=kfk−1,j−wi+vi)f_{k,j} = \max(f_{k-1,j} , \max_{s_i=k} f_{k-1,j-w_i} + v_i)fk,j​=max(fk−1,j​,si​=kmax​fk−1,j−wi​​+vi​)

显然我们已经得到了一个 O(n2V)\mathcal{O}(n^2V)O(n2V) 的算法,因为最大组数和 nnn 是同阶的,就算成 nnn 吧。

这里是没有办法优化的,因为 wiw_iwi​ 不连续,单调队列不行。

伪代码如下:

for(i=1;i<=n;i++) {read(s);for(j=1;j<=s;j++) read(w[j]) , read(v[j]);for(j=V;j>=0;j--)for(k=1;k<=s;k++)if(j>=w[k]) f[j]=max(f[j],f[j-w[k]]+v[k]);
}

有依赖的背包问题

这一道题目将是背包问题中最难的一种。

nnn 个物品,背包体积为 VVV.每个物品有 viv_ivi​(价值)和 wiw_iwi​(重量),只有 111 个。
每个物品有一个依赖物品 pip_ipi​,如果选了 iii 物品,则必须选 pip_ipi​ 号物品。求不超过背包体积的最大价值。数据保证 每个物品最多依赖于一个物品。(注:因此此类题常常用树形结构给出,儿子节点和父节点呈依赖关系)
n,V,vi,wi≤1×103n,V,v_i,w_i \leq 1 \times 10^3n,V,vi​,wi​≤1×103,时间限制 1s1s1s,空间限制 128MB128MB128MB.

显然,这种有依赖的背包并不容易,这和树形 dp\text{dp}dp 有些类似。简单的,如果选了 iii,所有 iii 的祖先都会被选。

一个非常显然的思路是,直接把所有子树的答案计算,合并即可。对于每一个子树,先不考虑根节点,进行背包,然后最后加上根节点的值即可。(因为根节点无论如何会被选,除非全不选)

代码略。

泛化物品

背包中比较玄乎的东西,选看选做。

泛化物品的精髓就是,每个物品没有固定的价值和重量,其价值随着分配的重量而变化。简单的,你用 xxx 的重量去放它,它就会产生 hxh_xhx​ 的价值贡献。而 hxh_xhx​ 的具体计算会给你一个多项式。这是非常好的一类问题。这一类问题的解决相当繁琐。

比方说吧,若背包容量为 101010,h1=3x+2h_1 = 3x + 2h1​=3x+2,一个物品 h2=2x+3h_2 = 2x+3h2​=2x+3,显然你直接放 111 个 h1h1h1,价值就可以达到 323232。这意思不是说贪心可以解决背包,而是这类问题不好解决。

简单的透露一下,该问题的复杂度应当是 O(V2)\mathcal{O}(V^2)O(V2),具体内容可以参考文末的 泛化物品_百度百科.

求方案数 & 具体方案

非常简单,只需要再开一个,算出 fff 后,用 与其同样维数的 ggg 记录当前最优解的方案数。只需要把所有的决策点的 ggg 统计一遍即可得到新的 ggg.

求具体方案也一样,一般来说会让你求字典序最小的,那么你用 与 fff 同样维数的 ggg 记录当前最优解且字典序最小的 那一个编号,这样就可以解决问题。

如果让你求全部的最优方案,你需要开一个 vector\text{vector}vector 和 fff 维数一样,类似于 vector<int> h[N][M] 的操作,开二维数量个 vector\text{vector}vector,记录所有答案,最后迭代返回。

由于方案数的增加呈指数性,一般只会求特殊的具体方案 / 方案数取模。

附录:背包问题的搜索解法

以最简单的 010101 背包为例,如何用朴素搜索解决?

大力搜索

枚举每个物品选或不选,这样复杂度是 O(2n)\mathcal{O}(2^n)O(2n) 的,可以加上剪枝(最主要的:就是当前答案加上所有未选的价值之和也不如之前得到的答案,或者是重量超出限制),但也只能 勉强 通过 n=25n=25n=25 的数据。

一个基于贪心的优化,将重量小 / 价值大 / 性价比高的物品先搜索,会适当提高效率。但是哪怕剪枝到极限,最多也是 n=26,27n=26,27n=26,27 的样子。

NP\text{NP}NP 完全问题

考虑这是一个 NP\text{NP}NP 完全,所以从模板题出发:

给定集合 SSS,求是否存在集合 XXX 使得 XXX 中的元素之和为 kkk. ∣S∣≤42|S| \leq 42∣S∣≤42.

显然大力枚举 2422^{42}242 是不可能通过的。我们考虑一个简单的优化。

将 SSS 等分 为两部分 S1S1S1 和 S2S2S2,然后枚举 S1S1S1 和 S2S2S2 内所有的可能,并两两相加验证。这样复杂度是 O(2⌊n2⌋)\mathcal{O}(2^{\lfloor \frac{n}{2} \rfloor})O(2⌊2n​⌋) 的,可以通过 n=42n=42n=42 的数据。

当然作者可以自行尝试分更多份,实际上大概率效率不会更高。

折半搜索

实际上上面解决 NP\text{NP}NP 完全的方法就是折半搜索的精髓了,对两边分别大力搜索即可实现 O(2⌊n2⌋)\mathcal{O}(2^{\lfloor \frac{n}{2} \rfloor})O(2⌊2n​⌋) 的复杂度。

搜索 VS DP\text{VS DP}VS DP

一般来说,设计到多重,完全,肯定是 dp\text{dp}dp.只有 010101 背包需要进行讨论!

如果 wi,V≤1016,n≤40w_i,V \leq 10^{16} , n \leq 40wi​,V≤1016,n≤40,那明显是折半搜索。

如果 wi,V,n≤5×103w_i,V,n \leq 5 \times 10^3wi​,V,n≤5×103,那明显是 dp\text{dp}dp.

总之,面向数据编程是没有毛病的,具体情况具体分析吧。

课后习题

(Acwing\text{Acwing}Acwing 上面 999 道题,洛谷\text{洛谷}洛谷 上 111 道,一共 101010 道不算多吧)

01\text{01}01 背包

完全背包

多重背包 - 单调队列

多重背包 111 - 大暴力

多重背包 222 - 二进制拆分

多重背包 333 - 单调队列

混合背包

二维费用背包

分组背包

有依赖的背包

参考资料

泛化物品_百度百科

再谈单调队列优化 背包九讲相关推荐

  1. 浅谈单调队列优化的DP

    为什么都是浅谈?深入就掉坑啊,掉坑就要填坑啊,填坑就会发现又挖了更多的坑啊,然后恶性循环啊. 这个坑必须要填的,拖了这么久了. 先拿TYVJ 1305来说吧,此题具体的题面没找到,代码简单的对拍了一下 ...

  2. 单调队列java_浅谈单调队列优化dp

    单调队列,即单调的队列.有时用于优化1D/1D方程. 例题 Tyvj1305 时间: 1000ms / 空间: 131072KiB / Java类名: Main 描述 输入一个长度为n的整数序列,从中 ...

  3. 多重背包单调队列优化思路_动态规划入门——多重背包与单调优化

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是算法与数据结构的第14篇文章,也是动态规划专题的第三篇. 在之前的文章当中,我们介绍了多重背包的二进制拆分的解法.在大多数情况下,这种 ...

  4. 多重背包:经典DP问题( 基本/二进制优化/单调队列优化 )

    目录 基本方法 **二进制优化 *****单调队列优化 多重背包问题描述:介于01背包和完全背包问题之间,每种物品的最大选取数目都是已知的. 对于一定数量( i )的物品有一个容量为( j )的背包, ...

  5. 多重背包单调队列优化思路_多重背包之单调队列优化理论性总结

    多重背包之单调队列优化: 若用F[j]表示对容量为j的背包,处理完前i种物品后,背包内物品可达到的最大总价值,并记m = min(n, j / v).放入背包的第i种物品的数目可以是:0.1.2--, ...

  6. 【学习笔记】多重背包相关优化——二进制优化/单调队列优化

    多重背包--二进制优化/单调队列优化 二进制优化 单调队列优化 代码都是 POJ1742 的,注意,那道题二进制优化会超时. 普通的多重背包式子,物品个数限制:c[i]c[i]c[i],单个物品价值 ...

  7. [Bzoj4182]Shopping(点分治)(树上背包)(单调队列优化多重背包)

    4182: Shopping Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 374  Solved: 130 [Submit][Status][Di ...

  8. 多重背包单调队列优化思路_多重背包问题

    题目描述: 无优化版本: int main(){int m, n;cin >> n >> m;for(int i = 1; i <= n; ++i){int v , w, ...

  9. 单调队列优化多重背包

    就是按照 % 体积的余数来分组,每组单调队列优化. 直接上模板好了. 1 #include <bits/stdc++.h> 2 3 typedef long long LL; 4 cons ...

  10. dp背包九讲(待补充,暂时前两讲)

    文章目录 背包九讲 一.01背包 二维dp 优化为一维 二.完全背包 二维dp 优化为一维 三.多重背包 数据范围很小时,变成01背包暴力 当数据范围较大时,利用二进制优化 二进制优化还不够用时,利用 ...

最新文章

  1. 详解void 0与undefined区别
  2. 利用python进行数据分析_利用python进行数据分析复现(1)
  3. JAVA课设日记本,java课程设计(日记本)
  4. matlab 平滑曲线连接_兔学 | MATLAB由离散数据点绘制曲线图像
  5. JS判断当前浏览器是否为IE内核
  6. 淘宝/天猫API ,获得淘口令真实url
  7. Python:统计字符个数
  8. 7-33 电话聊天狂人 (25 分)(map水题)
  9. vue3.0+vite跑项目遇到的问题
  10. unity-shader 2D - Sprite 影子
  11. 软件测试二分查找函数,二分查找
  12. CAD梦想画图中的“偏移命令”
  13. 机器学习--贝叶斯网
  14. c android显示gif动画,MFC显示GIF动画图片
  15. Centos7下的LibreOffice的搭建及自动化脚本部署
  16. 西涝东雪!数场冬季风暴轮番侵袭美国 多地预警
  17. 用手机GPRS使电脑上网
  18. 力扣977有序数组的平方(c++版)
  19. 测试使用linux日志定位BUG,Web测试中定位bug方法
  20. 测试基础篇之(postman接口和Fiddler测试)

热门文章

  1. Oralce性能优化-绑定变量窥视
  2. 互联网晚报 | 1月3日 星期一 | 春运首日火车票今日开售;中兴终端2021年出货量超1亿部;抖音上线“学习”频道...
  3. Niushop开源商城:618电商大趴开始预热啦!你的开源商城系统呢?
  4. 性能测试工程师职业现状分析
  5. 怎么进入修复计算机界面,开机进入启动修复界面不能启动win7电脑的修复办法...
  6. 学java对年龄有要求吗_Java学习有年龄限制吗,多大年纪就不能学习?
  7. 【毕业设计】大数据招聘数据分析可视化 - python
  8. 动态规划——计算二项式系数问题
  9. 斗战神单机版正在连接服务器,斗战神单机版完整
  10. mysql 常见问题处理_mysql常见问题处理