CF的区间DP(备用笔记)

news/2024/11/13 10:16:53/文章来源:https://www.cnblogs.com/mega-chimera/p/18535924

原自于vjudge的题单

前言

\(\quad\)(是不是链接点错了🤓)依旧拖着 线性DP

其他

\(\quad\) 可恶,vjudge吃我提交记录,还有「禁忌 Coloring Brackets 的二重奏」。

Zuma CF-607B

祖玛豪丸🤓👍

很豪写的 区间DP 题:

题目要求删除回文的字串,计算删除所有的字串的最小操作次数。

状态表示;\(f_{l,r}\) 表示在区间 \([l,r]\) 内的最小操作次数。

显然有一下结论:(此处()中,如果成立值为 1,不成立值为 0)

  • \(f_{i,i}=1\)
  • \(f_{i,i+1}=1+(a_i ≠ a_{i+1})\)
  • 其余状态全设为 \(inf\) 因为后面要计算最小值。

这样我们可以得出状态转移:

  • \(f_{l,r}=f{l+1,r-1}\quad (a[l]==a[r])\)
  • \(f_{l,r}=min_{k=1}^{r-1} \{ f_{l,k}+f_{k+1,r} \}\)

答案为 \(f_{1,n}\),时间复杂度 \(O(n^3)\)

code

for(int i=1;i<=n;i++){f[i][i]=1;f[i][i+1]=1+(a[i]!=a[i+1]);
}
for(int i=3;i<=n;i++){for(int l=1;l+i-1<=n;l++){int r=l+i-1;if(a[l]==a[r]) f[l][r]=f[l+1][r-1];for(int k=l;k<r;k++){f[l][r]=min(f[l][k]+f[k+1][r],f[l][r]);}}
}

Coloring Brackets CF-149D

为什么你在题单里出现了两次

代码还行,就是观感巨的 区间DP:

题目要求求括号序列的染色方案数,并且有一下限制:

  • 每个括号有三种染色方案,染红,染蓝和不染色。
  • 对于任意一个括号:它或者对应的匹配括号中的一个着色。
  • 相邻的着色括号颜色不同。

首先我们要找到每个括号所匹配的括号(找到它的另一半)用栈就可以轻松解决(代码在后面)。

然后就要考虑状态表示,套用模板设 \(f_{i,j}\) 发现限制很难维护,所以我们要进行修改,根据 限制 3 我们可以设计状态表示为:\(f_{i,j,p,q}\) 表示将区间 \([l,r]\) 染色的方案数,并且两端的颜色为 \(p,q\)。假设 0 代表不染色,1 代表染蓝色,2 代表染红色。

状态转移我们分类讨论:

l==r+1,即区间 \([l,r]\) 的长度为 2,形如 (),则 \(l\)\(r\) 一定是匹配括号,又因为只需给配对括号中的一个括号染色。只有一种方案,则 \(f_{l,r,0,1}=f_{l,r,1,0}=f_{l,r,0,2}=f_{l,r,2,0}=1\)

又由于 限制 3,\(f_{l,r,0,0} \quad f_{l,r,1,2} \quad f_{l,r,2,1} \quad f_{l,r,1,1} \quad f_{l,r,2,2}\) 的值为 0,不必赋初值。

括号 \(l\) 与括号 \(r\) 配对,形如 (....),容易知道 \(f_{l,r,0,0} \quad f_{l,r,1,2} \quad f_{l,r,2,1} \quad f_{l,r,1,1} \quad f_{l,r,2,2}\) 的值为 0,与上方证法相似。

剩下的情况我们以\(f_{l,r,0,1}\) 为例: 由于它左端为 0,右端为 1。所以它无法由所有的 \(f_{l,r,x,1}\) 转移而来,否则不符合 限制 3。

我们枚举所有可能的颜色 \(i\)\(j\) ,所以有状态转移:

\(j≠1\) \(\quad\) \(f_{l,r,0,1}+=f_{l+1,r-1,i,j}\)
\(j≠2\) \(\quad\) \(f_{l,r,0,2}+=f_{l+1,r-1,i,j}\)
\(i≠1\) \(\quad\) \(f_{l,r,1,0}+=f_{l+1,r-1,i,j}\)
\(i≠2\) \(\quad\) \(f_{l,r,2,0}+=f_{l+1,r-1,i,j}\)

括号 \(l\) 和括号 \(r\) 不匹配,形如 ..(...).....(...)..,我们分别处理出 \(f_{l,vis_l}\)\(f_{vis_l+1,r}\) 然后相乘。 若 \(vis_l\)\(vis_l+1\) 的颜色不相等需要特判,如果相等则不进行状态转移,因为这两个区间可以合并一起处理。(\(vis\) 为标记与该括号相匹配的另一个括号的位置)

状态转移:\(f_{l,r,i,q}+=f_{l,vis_l,i,j}*f_{vis_l+1,r,p,q}\)

最后用递归进行DP就可以了,不要忘了在计算过程与结果初取模,答案为所有颜色方案的加和。时间复杂度 \(O(n^3)\)

code

//处理 vis 函数
for(int i=1;i<=n;i++){if(s[i]=='(') sta.push(i);else{vis[sta.top()]=i;vis[i]=sta.top();sta.pop();}
}//递归 DP
void dfs(int l,int r){if(l+1==r){f[l][r][1][0]=f[l][r][2][0]=f[l][r][0][1]=f[l][r][0][2]=1;}else if(vis[l]==r){dfs(l+1,r-1);for(int i=0;i<=2;i++){for(int j=0;j<=2;j++){if(j!=1) f[l][r][0][1]=(f[l][r][0][1]+f[l+1][r-1][i][j])%mod;if(j!=2) f[l][r][0][2]=(f[l][r][0][2]+f[l+1][r-1][i][j])%mod;if(i!=1) f[l][r][1][0]=(f[l][r][1][0]+f[l+1][r-1][i][j])%mod;if(i!=2) f[l][r][2][0]=(f[l][r][2][0]+f[l+1][r-1][i][j])%mod;}}}else{dfs(l,vis[l]);dfs(vis[l]+1,r);for(int i=0;i<=2;i++){for(int j=0;j<=2;j++){for(int p=0;p<=2;p++){for(int q=0;q<=2;q++){if((j==1&&p==1)||(j==2&&p==2)) continue;f[l][r][i][q]=(f[l][r][i][q]+f[l][vis[l]][i][j]*f[vis[l]+1][r][p][q]%mod)%mod;}}}}}
}//计算答案
int ans=0;
for(int i=0;i<=2;i++){for(int j=0;j<=2;j++){ans=(ans+f[1][n][i][j])%mod;}
}

Recovering BST CF-1025D

二叉搜索树 + 区间 DP(不过只用了二叉搜索树的性质与定义):

题目要求我们判断所给序列能否建立一个二叉搜索树并且满足由边连接的两个顶点权值的最大公约数大于 1。

我们可以假设一个节点的 左儿子和右儿子 都是一个区间 \([l,r]\),则如果 区间 \([l,r]\) 为左儿子,那这个区间的根节点为的父亲为 \(r+1\);如果区间 \([l,r]\) 为右儿子,那这个区间的根节点的父亲为 \(l-1\)

显然我们可以设状态表示为 \(f_{l,r,k,0/1}\) 表示 \(k\) 为根节点 \(l\) 作为左儿子和 \(r\) 作为右儿子是否合法 0非法/1合法。但是观察数据范围,我们会 MLE ,并且会浪费很多空间来存放无效状态。

既然合起来无法实现,那我们可以将 \(f\) 数组分开,用 \(L_{l,r}\) 分别表示用区间 \([l,r-1]\)\(j\) 的左儿子是否合法,\(R_{l,r}\) 表示用区间 \([l+1,r]\)\(l\) 右儿子是否合法。

我们设 \(k\) 为区间 \([l,r]\) 的根,只要 \(L_{l,k}=R_{k,r}=1\) 则说明状态合法,可以转移,若转移完全,无法继续转移,则输出 \(Yes\),否则输出 \(No\)

处理 \(L\)\(R\),如果 \(k\) 可以和 \(l-1\) 连边,则 \(R_{l,r}\) 合法,如果 \(k\) 可以和 \(r+1\) 连边,则 \(L_{l,r}\) 合法。易知 \(L_{i,i}=R_{i,i}=1\)。时间复杂度:\(O(n^3)\)

code

for(int i=1;i<=n;i++){for(int j=i+1;j<=n;j++){if(gcd(a[i],a[j])>1){f[i][j]=f[j][i]=1;}}
}for(int l=n;l>=1;l--){for(int r=l;r<=n;r++){for(int k=l;k<=r;k++){if(L[l][k]&&R[k][r]){if(l==1&&r==n){puts("Yes");return 0;}if(f[l-1][k]) R[l-1][r]=1;if(f[k][r+1]) L[l][r+1]=1;}}}
}
puts("No");

Minimum Triangulation CF-1140D

非常有意思的题,有三种解法,我只想到了两种,看完大佬的题解后才明白第三种。

一,区间 DP

很好想到,设状态表示为:\(f_{i,j}\) 表示从 \(i\) 逆时针到 \(j\) 所需要的最小权值,可以暴力枚举割点 \(k\) 计算每一个 \(f\) 的值。状态转移为:\(f_{i,j}=min\{ f_{i,k}+f_{k,j}+i*j*k \}\)。最后的 \(f_{1,n}\) 为答案,时间复杂度 \(O(n^3)\)

code

for(int i=n-2;i>=0;i--){for(int j=i+2;j<=n;j++){for(int k=i+1;k<=j;k++){f[i][j]=min(f[i][j],f[i][k]+f[k][j]+i*j*k);}}
}

二,数学分析

我们发现只要所有三角形都是由 1 释放两条线形成的时,三角剖分的权重最小,显然,我们的答案为:\(\sum_{i=2}^{n-1} i*(i+1)\),我们只需枚举计算即可,时间复杂度 \(O(n)\)

三,进一步优化

我们在二中的式子加上 \(1×2\) 最后在减去。由于所有式子可以化为:\(n(n-1)=\frac{1}{3}((n-1)n(n+1)-(n-2)(n-1)n)\) 。所以我们可以将原式子化为;\(\frac{1}{3}(n-1)n(n+1)-2\),这样就可以快速计算答案了,时间复杂度为 \(O(1)\)

Array Shrinking CF-1312E

很板的一道 区间DP:

题目描述:给定一个序列 \(a\),如果 \(a_i=a_{i+1}\) ,我们可以用 \(a_i+1\)\(a_{i+1}+1)\) 来替换它,求可以得到的最小序列长度。

我们设状态表示为 \(f_{i,j}\) 表示区间 \([l,r]\) 合并所得的最小长度。但是我们发现,如果这样维护,我们无法在下次转移中知道合并后的区间 &[l,r]& 中的值,所以我们考虑令设 \(w_{l,r}\) 表示区间 \([l,r]\) 的和。

所以状态转移为:\(f_{l,r}=min\{ f_{l,k}+f_{k+1,r} \}\)
如果 \(f_{l,k}=f_{k+1,r}=1\) 则说明区间 \([l,r]\) 的长度为 2,如果此时 \(w_{l,k]=w_{k+1,r]\),则说明区间内的两个值相等,可以合并,则:\(f_{l,r}=1\) \(\quad\) \(w_{l,r}=w_{l,k}+1\)

最后答案为 \(f_{1,n}\) ,时间复杂度为 \(O(n^3)\)

code

for(int i=2;i<=n;i++){for(int l=1;l+i-1<=n;l++){int r=l+i-1;for(int k=l;k<r;k++){f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]);if(f[l][k]==1&&f[k+1][r]==1&&w[l][k]==w[k+1][r]){f[l][r]=1;w[l][r]=w[k+1][r]+1;}}}
}

Connecting Vertices CF-888F

非常好的题号,使我的代码旋转

我们可以先把多边形拉成一条链,题目条件就可以转化为任意两条线段不能相交。

考虑 区间 DP ,设 \(f_{l,r}\) 为将区间 \([l,r]\) 连在一起的方案数。

如果 \([l,r]\) 连边,则为 \(f_{l,r}+=f_{l,k}*f{k+1,r}\)
如果 \({l,r}\) 不连边,则为 \(f_{l,r}+=f_{l,k}*f_{k,r}\)

但是在实际运行中会出错,会错误统计相关信息,所以要考虑修改状态表示,发现上述会考虑连边与不连边两种情况,我们将它具化到状态表示为 \(f_{l,r,0/1}\) 表示区间 \([l,r]\) 不连边(0)或连边(1)的的方案数。我们将 \(f_{l,r,0}+f_{l,r,1}\) 即为总方案数。

状态转移方程:

处理 \(f_{l,r,0}\),枚举断点转移:\(f_{l,r,0}=(f_{l,k,0}+f_{l,k,1})*(f_{k+1,r,0}+f_{k+1,r,1})\)
处理 \(f_{l,r,1}\),枚举断点,但是要算 \([l,k]\) 之间强制连边的方案,需要满足 \(g_{l,k}=1\) \(f_{l,r,1}=f_{l,k,0}*(f_{k,r,0}+f_{k,r,1})\)

最后答案为 \(f_{1,n,0}+f_{1,n,1}\) ,初始值 \(f_{i,i,0}=1\) 时间复杂度为 \(O(n^3)\)

code

for(int i=2;i<=n;i++){for(int l=1;l+i-1<=n;l++){int r=l+i-1;if(g[l][r]){for(int k=l;k<r;k++){f[l][r][0]=(f[l][r][0]+(f[l][k][0]+f[l][k][1])*(f[k+1][r][0]+f[k+1][r][1])%mod)%mod;}}for(int k=l+1;k<r;k++){if(g[l][k]){f[l][r][1]=(f[l][r][1]+f[l][k][0]*(f[k][r][0]+f[k][r][1])%mod)%mod;} }}
}

Clear the String CF-1132F

又事一道很板的区间 DP :

题目描述:给定一个字符串,我们可以删去连续的字符相同的字串,求删除完这个字符串的最小操作次数。

状态表示:\(f_{l,r}\) 表示删除区间 \([l,r]\) 的最小操作次数。

枚举断点,判断区间能否被一次删除,合并两个区间的操作次数。由此得状态转移为:\(f_{l,r}=min\{ f_{l,k}+f_{k+1,r}+(s_l ≠ s_k) \}\)

最终答案为 \(f_{1,n}\) 复杂度 \(O(n^3)\)

code

for(int i=2;i<=n;i++){for(int l=1;l+i-1<=n;l++){int r=l+i-1;for(int k=l;k<r;k++){f[l][r]=min(f[l][r],f[l][k]+f[k+1][r]-(s[l]==s[r]));}}
}

后言:

\(\quad\) vjudge把我提交记录吐出来了,可喜可贺,可喜可贺😄。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/831601.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024/11/11

软件设计 实验12:外观模式 在计算机主机(Mainframe)中,只需要按下主机的开机按钮(on()),即可调用其他硬件设备和软件的启动方法 ,如内存(Memory)的自检(check())、CPU的运行(run())、硬盘(HardDisk)的读取(read())、操作系统(OS)的载入(load()),如果某一过程发生错误则计算…

2024.11.6(周三)

用透明组合模式实现教材中的“文件夹浏览”这个例子。 实验要求: 1.文件的执行不需真正实现,只需简单提示即可; 2.提交源代码; 3.注意编程规范。1、类图2、源代码 #include <iostream> #include <string> #include<list> using namespace std;class Abst…

2024.11.7(周四)

用装饰模式模拟手机功能的升级过程:简单的手机(SimplePhone)在接收来电时,会发出声音提醒主人;而JarPhone除了声音还能振动;更高级的手机(ComplexPhone)除了声音、振动外,还有灯光闪烁提示。 实验要求: 1.提交类图; 2.提交源代码; 3.注意编程规范。1、类图2、源代码 #i…

2024.11.5(周二)

用桥接模式实现在路上开车这个问题,其中,车可以是car或bus,路可以是水泥路或沥青路。 实验要求: 1.画出对应的类图; 2.提交源代码; 3.注意编程规范。1、类图2、源代码 (1) Bus.java package test;public class Bus implements Vehicle{@Overridepublic void run() {Sy…

CFAT:三角窗口实现图像超分辨率

CFAT:三角窗口实现图像超分辨率基于变换器的模型通过利用其固有的捕获复杂上下文特征的能力,彻底改变了图像超分辨率(SR)的效果。如今,在Transformer架构中使用的重叠矩形移位窗口技术是超分辨率模型中的一种常见做法,可以提高图像放大的质量和鲁棒性。然而,它在边界处存…

CFAT:释放三角窗口实现图像超分辨率

CFAT:释放三角窗口实现图像超分辨率基于变换器的模型通过利用其固有的捕获复杂上下文特征的能力,彻底改变了图像超分辨率(SR)的效果。如今,在Transformer架构中使用的重叠矩形移位窗口技术是超分辨率模型中的一种常见做法,可以提高图像放大的质量和鲁棒性。然而,它在边界…

读数据工程之道:设计和构建健壮的数据系统34读后总结与感想兼导读

读后总结与感想兼导读1. 基本信息 数据工程之道:设计和构建健壮的数据系统[美]乔里斯(Joe Reis),[美]马特豪斯利(Matt Housley)著机械工业出版社,2024年2月出版1.1. 读薄率 书籍总字数473千字,笔记总字数109584字。 读薄率109584473000≈23.17% 1.2. 读厚方向Data Mesh权威指…

鸿蒙NEXT开发案例:抛硬币

【1】引言(完整代码在最后面) 本项目旨在实现一个简单的“抛硬币”功能,用户可以通过点击屏幕上的地鼠图标来模拟抛硬币的过程。应用会记录并显示硬币正面(地鼠面)和反面(数字100面)出现的次数。为了增强用户体验,我们还添加了动画效果,使抛硬币的过程更加生动有趣。 …

【CodeForces训练记录】Codeforces Round 986 (Div. 2)

训练情况赛后反思 C题逆风翻盘,可能勉强青名了。A题愣神了,我觉得还能再做的快一点。 A题 给定一个字符串,NWSE,重复着字符串走,我们直接模拟即可,用 while 来判断是否走到终点,然后对于不可能走到的终点,我选择了一个不会超时的步数范围,超出就跳出 while 即可,最后…

24. 使用MySQL之使用游标

1. 游标 由前几章可知,MySQL检索操作返回一组称为结果集的行。这组返回的行都是与SQL语句相匹配的行(零行或多行)。 使用简单的SELECT语句,例如,没有办法得到第一行、下一行或前10行,也不存在每次一行地处理所有行的简单方法(相对于成批地处理它们)。 有时,需要在检索…

Python clickhouse-driver 类库使用学习总结

实践环境 python3 .9.13 clickhouse-driver 0.2.9 实践操作 # -*- coding:utf-8 -*-import clickhouse_driverif __name__ == __main__:host = 192.168.88.131port = 9000 # 注意,不能使用默认的8123username = testaccpassword = test1234database = default# 连接方式1# con…

随波逐流工具使用_Week1

跟着大师傅的公众号做题的week1 来源以及说明 (文章主要是了解怎样使用长弓三皮大师傅的随波逐流工具,wp以及附件来自大师傅长弓三皮) (这周主要是做笔记的软件老是出现问题,有一些笔记有点乱,后面慢慢改进) 软件及题目下载 http://www.1o1o.xyz/bo_softdown.html CTF题目wr…