Codeforces2000分左右DP泛刷

本文详细介绍了Codeforces上适合2000分左右选手练习的动态规划题目,包括Porcelain、Gourmet choice、Famil Door and Brackets等多个题目,分析了它们的题意、解决方案和解题思路,涉及子集、分组背包、括号序列等多种动态规划问题,旨在帮助读者掌握动态规划的应用技巧。
摘要由CSDN通过智能技术生成

乱七八糟的DP题随便刷刷

CF148E - Porcelain

题意:

  • n n n 层货架,每层上有 k i k_i ki 个东西,每个东西存在一个价值 v i v_i vi
  • 现在至多可以拿 m m m 个东西,每一次只能从货架的最左或最右端拿走,求可以拿到的最大价值
  • n , k , v i ≤ 100 , m ≤ 10000 n,k,v_i \leq 100,m \leq 10000 n,k,vi100,m10000

思路:

  • 首先可以明确,第 i i i 层拿 j j j 个东西的最优价值都是确定的,我们只需要 O ( n 3 ) O(n^3) O(n3) 枚举当前第 i i i 层拿 j j j 个东西,左边选了 k k k 个即可。

  • 接着我们可以把第 i i i 层的 k i k_i ki 个东西看一组物品,那么就变成了以选取物品个数为体积,物品价值为重量的一个分组背包问题,复杂度 O ( n m k ) O(nmk) O(nmk)
    注意分组背包先枚举第几组,再倒序循环体积,最后在枚举组内物品

CF1131D - Gourmet choice

题意:

  • 有两个正整数序列 a , b a,b a,b,长度分别为 n , m n,m n,m,现在给出给出所有 a i a_i ai b j b_j bj 的大小关系,构造出最大元素最小的方案
  • 其中大小关系包含大于,小于以及等于
  • n , m ≤ 1000 n,m \leq 1000 n,m1000

思路:

  • 如果大小关系中没有等于,我们很容易想到直接在 D A G DAG DAG 上做 d p dp dp,令 f [ u ] f[u] f[u] 代表点 u u u 的最终答案,则 f [ t o ] = m a x ( f [ t o ] , f [ u ] + 1 ) f[to]=max(f[to],f[u]+1) f[to]=max(f[to],f[u]+1),并且通过出队列数判断是否无解

  • 那么现在的问题就是考虑:如果解除等于这一关系限制?
    考虑到没法直接连边,但是把相当的点看作一个点集,那么这个点集与此外其他点的关系就很好处理了,并且一个点集内的相互关系我们可以不用处理。于是我们可以使用缩点来处理所有值相等的点

  • 我一开始是用并查集直接维护一个点集的最大值,零入度的点个数以及点集个数,然后整个点集的点都符合零入度了就一起得到最终答案并且入队列。。。。。这样显然很麻烦,可以在一开始就把他们缩成一个点,然后直接 D A G DAG DAG d p dp dp 即可,非常无脑

CF629C - Famil Door and Brackets

题意:

  • 给出一个长度为 m m m 的只包含 ′ ( ′ '(' ( ′ ) ′ ')' ) 的序列 S S S,要求构造只包含 ′ ( ′ '(' ( ′ ) ′ ')' ) 的序列 P , Q P,Q P,Q,使得按照 P , S , Q P,S,Q P,S,Q 顺次连接得到长度为 n n n 的合法括号序列 S ′ S' S,其中 P , Q P,Q P,Q 都可以为空
  • 1 ≤ m ≤ n ≤ 1 0 5 , n − m ≤ 2000 1 \leq m \leq n \leq 10^5,n-m \leq 2000 1mn105,nm2000

思路:

  • 设平衡度为左括号与右括号的个数之差,考虑到 n − m ≤ 2000 n-m \leq 2000 nm2000 ,我们枚举第一个序列 P P P 的长度与平衡度,那么 Q Q Q 的状态也已经知道了,我们利用乘法原理求出方案数即可

  • 序列 P P P 需要满足的要求:
    1.所有位置的平衡度都要恒大于 0 0 0
    2.如果序列 S S S 所有位置的最小平衡度 b b b 小于 0 0 0,那么序列 P P P 的整体平衡度必须大于 P P P,相当于给 S S S 作铺垫以保证最终 S ′ S' S 是合法序列

  • 序列 Q Q Q 需要满足的要求:
    1.所有位置的平衡度都要恒大于 P + S P+S P+S 最终的平衡度的相反数
    2. P + S + Q P+S+Q P+S+Q 最终的平衡度为 0 0 0

  • 显然对于 P P P,我们只需要按照构造合法括号序列的方法,设 d p [ i ] [ j ] dp[i][j] dp[i][j] 代表前 i i i 个平衡度为 j j j 的方案数, e z : d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + d p [ i − 1 ] [ j + 1 ] ez:dp[i][j]=dp[i-1][j-1]+dp[i-1][j+1] ez:dp[i][j]=dp[i1][j1]+dp[i1][j+1],显然 P P P 的方案数就是 d p [ i ] [ j ] dp[i][j] dp[i][j]

  • 那么对于 Q Q Q,如果正着看显然每次都要按照 P + S P+S P+S 最终的平衡度做一次dp,但是如果我们把原串反转过来,把前缀的定义也反转,那么方案数就是 d p [ n − m − i ] [ j + c n t ] dp[n-m-i][j+cnt] dp[nmi][j+cnt] 其中 c n t cnt cnt S S S 的平衡度。这里没有具体的什么证明解释,感性理解就好hh。

CF895C - Square Subsets

题意:

  • 对于一个长度为 n n n 的数组 a a a,求从 a a a 中选择一个非空子集满足两两乘积为平方数的方案数
  • 1 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 70 1 \leq n \leq 10^5,1 \leq a_i \leq 70 1n105,1ai70

思路:

看到 a i ≤ 70 a_i \leq 70 ai70 质因子就 19 19 19 个,第一眼状压dp。。。

具体来说,平方数的每个质因子个数都为偶数,那我们只需要判断子集的质因子的奇偶即可。

我们设二进制数 m a s k mask mask 代表一个集合的质因子的奇偶性,那么第 i i i 个质因子为奇数则设为 1 1 1,那么显然根据奇偶关系,两个集合合并 m a s k mask mask 应该做异或操作

设前 f i , m a s k f_{i,mask} fi,mask 为前 i i i 个数中质因子奇偶情况为 m a s k mask mask 的方案数,则 f i , m a s k ⊕ x = f i , m a s k ⊕ x + f i − 1 , m a s k f_{i,mask \oplus x}=f_{i,mask \oplus x}+f_{i-1,mask} fi,maskx=fi,maskx+fi1,mask,其中 x x x 代表第 i i i 个数的质因子奇偶情况。但是这么做复杂度显然 O ( 1 0 5 × 1 0 6 ) O(10^5 \times10^6) O(105×106) 太夸张了,完全没必要一个一个数去枚举,因为值域只有 70 70 70,且子集方案数与顺序无关,我们直接枚举值即可。

那么新问题又来了。。对于值 v a l val val,有 k k k 个这样的数加入到之前的的子集中,由于遵循异或的规律,那么加入奇偶个数的数结果都不同,也就是说大致分成以下两种情况:

  • ∑ i ≤ k , i ≡ 1   ( m o d 2 ) C k i = 2 k − 1 \sum_{i \leq k ,i\equiv 1 \ (mod 2)} C_k^i=2^{k-1} ik,i1 (mod2)Cki=2k1 m a s k mask mask 异或上 v a l val val 的奇偶情况 x x x
  • ∑ i ≤ k , i ≡ 0   ( m o d 2 ) C k i = 2 k − 1 \sum_{i \leq k ,i\equiv 0 \ (mod 2)} C_k^i=2^{k-1} ik,i0 (mod2)Cki=2k1 m a s k mask mask 不变)

综上得到转移方程
{ f i , m a s k = f i , m a s k + f i − 1 , m a s k ∗ 2 k − 1 f i , m a s k = f i , m a s k + f i − 1 , m a s k ⊕ x ∗ 2 k − 1 \left\{ \begin{aligned} f_{i,mask}=f_{i,mask}+f_{i-1,mask}*2^{k-1}\\ f_{i,mask}=f_{i,mask}+f_{i-1,mask \oplus x}*2^{k-1}\\ \end{aligned} \right. { fi,mask=fi,mask+fi1,mask2k1fi,mask=fi,mask+fi1,maskx2k1

CF1012C - Hills

题目描述:

给出一个长度为 n n n 的序列,现在每次操作可以使某一位置的数减一(可以减为负数)。目标是求出使序列至少有 k k k 个数满足严格大于它旁边的两个数(第 1 1 1 个数只用严格大于第 2 2 2 个数,第 n n n 个数只用严格大于第 n − 1 n−1 n1 个数)的最小操作数

现在求对于 k ∈ [ 1 , ⌈ n 2 ⌉ ] k \in [1,\lceil \frac n 2 \rceil] k[1,2n] 时的答案

1 ≤ n ≤ 5000 1 \leq n \leq 5000 1n5000

solution:

我们需要求出任意 k k k 下的最小操作数,那么很明显的一个方向就是设置一维记录满足要求的个数去做DP,这题的状态比较灵活,这里以其中一种为例作介绍

首先根据题意,想想为什么 k k k 的上界是 ⌈ n 2 ⌉ \lceil \frac n 2 \rceil 2n,因为严格的偏序关系在相邻两数之中至多只能有一个数字满足,那么最好情况就是隔一个满足一个。

那么明确了这一点,我们可以开始设置转移状态。

首先 f ( i , j ) f(i,j) f(i,j) 代表前 i i i 个数中有 j j j 个数满足关系,然而在想转移方程的时候我们发现这样没法保证偏序关系的合法性,并且由于我们不知道前面一个数有没有操作过,我们根本没法转移

那么我们只需要多设置一维,把之前的情况用状态描述清楚即可。

这里又有很多种设置方法,我们设 f ( i , j , k ) f(i,j,k) f(i,j,k) 代表前 i i i 个数中有 j j j 个数满足关系,并且用 k k k 来描述 a i a_i ai a i − 1 a_{i-1} ai1 的状态,具体的:

  • k = 0 k=0 k=0 时代表 a i − 1 a_{i-1} ai1 a i a_i ai 都不满足
  • k = 1 k=1 k=1 时代表 a i a_i ai 满足, a i − 1 a_{i-1} ai1 不满足
  • k = 2 k=2 k=2 时代表 a i − 1 a_{i-1} ai1 满足, a i a_i ai 不满足

转移方程:

如果当前 k = 0 k=0 k=0,显然必须从 a i − 1 a_{i-1} ai1 不满足的状态转移过来

f ( i , j , 0 ) = m i n { f ( i − 1 , j , 0 ) , f ( i − 1 , j , 2 ) } f(i,j,0)=min \{ f(i-1,j,0),f(i-1,j,2) \} f(i,j,0)=min{ f(i1,j,0),f(i1,j,2)}

如果当前 k = 1 k=1 k=1,那么也必须从 a i − 1 a_{i-1} ai1 不满足条件的的状态转移过来,并且要使 a i − 1 a_{i-1} ai1 的值严格小于 a i a_i ai,根据几种情况, a i − 1 a_{i-1} ai1 的值肯定为了使 a i − 2 a_{i-2} ai2 满足条件而减少,所以我们需要判断:

f ( i , j , 1 ) = m i n { f ( i − 1 , j − 1 , 0 ) + m a x ( 0 , a i − 1 − a i + 1 ) , f ( i − 1 , j − 1 , 2 ) + m a x ( 0 , m i n ( a i − 2 − 1 , a i − 1 ) − a i + 1 ) } f(i,j,1)=min \{ f(i-1,j-1,0)+max(0,a_{i-1}-a_i+1),f(i-1,j-1,2)+max(0,min(a_{i-2}-1,a_{i-1})-a_i+1) \} f(i,j,1)=min{ f(i1,j1,0)+max(0,ai1ai+1),f(i1,j1,2)+max(0,min(ai21,ai1)ai+1)}

如果当前 k = 2 k=2 k=2,显然必须从 a i a_{i} ai 满足的状态转移过来

f ( i , j , 2 ) = f ( i − 1 , j , 1 ) + m a x ( 0 , a i − 1 − a i − 1 ) f(i,j,2)=f(i-1,j,1)+max(0,a_{i-1}-a_i-1) f(i,j,2)=f(i1,j,1)+max(0,ai1ai1)

综上,我们可以对于最后的 k k k,只需取 m i n { f ( n , k , 0 ) , f ( n , k , 1 ) , f ( n , k , 2 ) } min \{ f(n,k,0),f(n,k,1),f(n,k,2) \} min{ f(n,k,0),f(n,k,1),f(n,k,2)} 即可。

转移时可以先把 i = 1 i=1 i=1 时的情况手动转移,然后就不需要特判一些边界了。并且为了节省空间这题显然可以滚动数组,甚至不需要滚,可以省略一维,然后根据 k k k 的具体转移要求将 j j

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值