考虑最终有石子的位置的状态,判断一种状态是否可行

反过来,依次删除石子,删除条件是:当删除的石子是该段最后一个(即其两边都没有石子了),要求除其以外,每个连续段旁边的两个点都与其颜色不同

构造一种删除方案:

除了最先删除的段以外,必然有一时刻(即该段最后一个位置删除时)其余段旁边的两个点颜色都相同,假设都是颜色$c$,另外一种颜色为$c'$

接下来,如果一个段内含有$c'$,那么必然可以直接删除该段且不劣,因此我们删除了所有含有$c'$的段

而对于剩下的段,其所有位置以及旁边都为颜色$c$,那么若有超过1段,则一定不合法,因此我们要让段尽量长(以包含$c'$来删除),即在构造段旁边颜色为$c$时,找到第一个$c$即可

总结一下,考虑合法当且仅当存在颜色$c$,满足以下条件:

1.对于最先删除的段,其中包含颜色$c'$

2.对于最晚删除的段,其与其旁边的位置包含至少两个$c$(即含有$cc$的子序列)

3.对于其余的段,其与其旁边的位置包含一个$cc'c$的子序列

(特别的,如果仅有1个段必然是可行的)

先枚举颜色$c$,对每一个颜色$c$求出最短的方案再取min即可

考虑dp,用$f_{i,j,0/1,0/1}$表示前$i$个字母,$i$所处的串状态为$j$,是否已经出现要强制最先删除/最后删除的段(不包括$i$所处的段)的最短长度,向后转移即可

状态$j$的定义方式有很多,只需要能够转移、能够确定该串的类型即可(例如与$cc'c$的最长公共子序列长度/未被选择)

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 #define get_min(x,y) x=min(x,y)
5 int n,ans,f[N][5][2][2];
6 char s[N],t[N];
7 int calc(){
8 memset(f,0x3f,sizeof(f));
9 f[0][0][0][0]=0;
10 for(int i=0;i<=n;i++)
11 for(int j=0;j<5;j++)
12 for(int p=0;p<2;p++)
13 for(int q=0;q<2;q++){
14 if (t[i+1]=='_'){//不选
15 if (!j)get_min(f[i+1][0][p][q],f[i][j][p][q]);
16 if (((j==2)||(j==3))&&(!p)&&(s[i+1]=='w'))get_min(f[i+1][0][1][q],f[i][j][p][q]);
17 if ((j==3)&&(s[i+1]=='w')||(j==4))get_min(f[i+1][0][p][q],f[i][j][p][q]);
18 }
19 int jj=max(j,1);
20 if ((jj==1)&&(s[i]=='w'))jj=2;
21 if ((jj==2)&&(s[i+1]=='b'))jj=3;
22 if ((jj==3)&&(s[i+1]=='w'))jj=4;
23 get_min(f[i+1][jj][p][q],f[i][j][p][q]+1);
24 if (!p){
25 int jj=max(j,1);
26 if ((jj==1)&&(s[i]=='w'))jj=2;
27 if ((jj==2)&&(s[i+1]=='b'))jj=3;
28 if ((j>=2)&&((jj==2)||(jj==3))&&(s[i+1]=='w'))jj=4;
29 get_min(f[i+1][jj][1][q],f[i][j][p][q]+1);
30 }
31 if (!q){
32 int jj=max(j,1);
33 if ((jj==1)&&(s[i]=='w'))jj=2;
34 if ((jj<=3)&&(s[i+1]=='b'))jj=4;
35 if ((jj==3)&&(s[i+1]=='w'))jj=4;
36 get_min(f[i+1][jj][p][1],f[i][j][p][q]+1);
37 }
38 }
39 for(int i=0;i<2;i++)
40 for(int j=0;j<2;j++)ans=min(ans,min(f[n+1][0][i][j],f[n+1][4][i][j]));
41 }
42 int main(){
43 scanf("%d%s%s",&n,s+1,t+1);
44 int x=0,y=0;
45 for(int i=1;i<=n;i++)
46 if (t[i]=='o'){
47 if (!x)x=i;
48 y=i;
49 }
50 t[n+1]='_';
51 ans=y-x+1;
52 s[0]='w';
53 s[n+1]='b';
54 calc();
55 for(int i=0;i<=n+1;i++)
56 if (s[i]=='w')s[i]='b';
57 else s[i]='w';
58 calc();
59 printf("%d",ans);
60 }

[atARC109F]1D Kingdom Builder的更多相关文章

  1. ARC109F - 1D Kingdom Builder

    一行格子,其中小于\(0\)的格子为白色,大于\(n\)的格子为黑色,中间的格子颜色由题目给出. 有一些格子需要被标记.标记按照以下规则进行:选择一个颜色\(c\),找到一个未标记的 旁边有标记点的 ...

  2. [atARC109E]1D Reversi Builder

    归纳每一次操作后必然是两个颜色相同的连续段(即ww...bb...或bb...ww...),对操作的位置分类讨论不难证明正确性 当$c_{1}=c_{n}$,由于端点颜色不会修改,再根据该结论,可以得 ...

  3. AtCoder Regular Contest 109

    Contest Link 为什么还没有 Official Editorial 啊--哦,原来是日文题解,那没事了. A - Hands 有两幢 100 层的楼房 \(A,B\) ,将地面所在的楼层称为 ...

  4. TDictionary 是delphi用的,c++builder用起来太吃力。

    TDictionary 是delphi用的,c++builder用起来太吃力.c++还是用std::map代替.c++d map很好用啊.https://blog.csdn.net/ddkxddkx/ ...

  5. 23种设计模式--建造者模式-Builder Pattern

    一.建造模式的介绍       建造者模式就是将零件组装成一个整体,用官方一点的话来讲就是将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示.生活中比如说组装电脑,汽车等等这些都是建 ...

  6. PHP设计模式(五)建造者模式(Builder For PHP)

    建造者模式:将一个复杂对象的构造与它的表示分离,使同样的构建过程可以创建不同的表示的设计模式. 设计场景: 有一个用户的UserInfo类,创建这个类,需要创建用户的姓名,年龄,爱好等信息,才能获得用 ...

  7. 每天一个设计模式-7 生成器模式(Builder)

    每天一个设计模式-7 生成器模式(Builder) 一.实际问题 在讨论工厂方法模式的时候,提到了一个导出数据的应用框架,但是并没有涉及到导出数据的具体实现,这次通过生成器模式来简单实现导出成文本,X ...

  8. Stack Overflow 排错翻译 - Closing AlertDialog.Builder in Android -Android环境中关闭AlertDialog.Builder

    Stack Overflow 排错翻译  - Closing AlertDialog.Builder in Android -Android环境中关闭AlertDialog.Builder 转自:ht ...

  9. Joshua Bloch错了? ——适当改变你的Builder模式实现

    注:这一系列都是小品文.它们偏重的并不是如何实现模式,而是一系列在模式实现,使用等众多方面绝对值得思考的问题.如果您仅仅希望知道一个模式该如何实现,那么整个系列都会让您失望.如果您希望更深入地了解各个 ...

随机推荐

  1. 实战-快手H5字体反爬

    实战-快手H5字体反爬 前言 快手H5端的粉丝数是字体反爬,抓到的html文本是乱码 <SPAN STYLE='FONT-FAMILY: kwaiFont;'></SPA ...

  2. Java:ConcurrentHashMap类小记-2(JDK7)

    Java:ConcurrentHashMap类小记-2(JDK7) 对 Java 中的 ConcurrentHashMap类,做一个微不足道的小小小小记,分三篇博客: Java:ConcurrentH ...

  3. [no code][scrum meeting] Alpha 3

    项目 内容 会议时间 2020-04-07 会议主题 技术规格说明书review 会议时长 1h30min 参会人员 产品经理+后端技术组长(伦泽标)+OCR竞品调研成员(叶开辉)+架构文档负责(黎正 ...

  4. springBoot服务整合线程池ThreadPoolTaskExecutor与@Async详解使用

    ThreadPoolExecutor:=======这个是java自己实现的线程池执行类,基本上创建线程池都是通过这个类进行的创建.ThreadPoolTaskExecutor:========这个是 ...

  5. poi实现生成下拉选

    在我们日常开发中,经常需要使用poi操作excel文件,现在就简单介绍一下在poi中是如何生成下拉选的. 1.创建workbook 2.创建数据约束 3.设置数据的有效性 @Test public v ...

  6. 计算机网络传输层之TCP协议(tcp协议特点、tcp报文段首部格式、tcp连接建立---三次握手、tcp连接释放---四次握手)

    文章转自:https://blog.csdn.net/weixin_43914604/article/details/105516090 学习课程:<2019王道考研计算机网络> 学习目的 ...

  7. 『学了就忘』Linux基础 — 7、补充:安装Linxu系统时设置硬盘挂载说明

    目录 (1)新建一个/home分区 (2)再创建一个/boot分区. (3)创建一个swap分区 (4)最后剩余的空间全部分给根目录 (5)总结 上一篇在VMwar虚拟机中安装Linux操作系统中ht ...

  8. ShardingSphere-初见

    目录 概述 认识shardingjdbc shardingjdbc功能架构图 认识Sharding-Proxy 三个组件的比较 ShardingJdbc混合架构 ShardingShpere的功能清单 ...

  9. 验证人员应该以何种角度阅读spec

    转载:验证人员应该以何种角度阅读spec - 微波EDA网 (mweda.com) 在开发流程中,设计和验证人员关注的点肯定是不一样的,尤其在spec的理解上,验证人员往往需要有自己独立的理解.在拿到 ...

  10. hdu 1083 Courses(二分图最大匹配)

    题意: P门课,N个学生.     (1<=P<=100    1<=N<=300) 每门课有若干个学生可以成为这门课的代表(即候选人). 又规定每个学生最多只能成为一门课的代 ...