题解:AT_joisc2019_h ランプ (Lamps)
题意
走廊上有排成一列的
盏灯,给出了一个 串 表示其开关状态( 表示打开, 表示关闭)。现在想要把这 盏灯变成目标状态 。 你有三种操作:
- OFF 操作:选择一个区间,将区间内所有的灯关闭。
- ON 操作:选择一个区间,将区间内所有的灯打开。
- TOG 操作:选择一个区间,在区间内关闭原本打开的灯,打开原本关闭的灯。
求将灯的状态从
变为 的最小的操作数。
分析
首先,任意两个有交的翻转操作
所以在最优情况下存在翻转操作互不相交的方案。
然后考虑覆盖操作。
首先显然覆盖操作的区间要么不交,要么一个包含另一个。
正确性显然。
后一种情况可以化为先覆盖再翻转,所以存在覆盖操作互不相交的方案。
最后考虑覆盖操作和翻转操作之间的关系。
如果是先翻转再覆盖,此时翻转区间一定包含覆盖区间。
那么就可以先覆盖相反的值,然后再翻转。
所以存在覆盖操作互不相交,且翻转操作互不相交,且先覆盖再翻转的方案。
据此,可以进行线性 dp。
令
分情况讨论是否需要添加翻转即可。
Code
#include<bits/stdc++.h> using namespace std; #define maxn 1000006 int dp[maxn][3]; char S[maxn], T[maxn]; int main() { int n; scanf("%d%s%s", &n, S+1, T+1); dp[1][0]=(T[1]!='0')+1; dp[1][1]=(T[1]!='1')+1; dp[1][2]=(T[1]!=S[1]); for(int i=2;i<=n;i++) dp[i][1]=min({dp[i-1][0]+(T[i]!='1')*(T[i-1]=='0')+1, dp[i-1][1]+(T[i]!='1')*(T[i-1]=='1'), dp[i-1][2]+(T[i]!='1')*(T[i-1]==S[i-1])+1}), dp[i][0]=min({dp[i-1][0]+(T[i]!='0')*(T[i-1]=='0'), dp[i-1][1]+(T[i]!='0')*(T[i-1]=='1')+1, dp[i-1][2]+(T[i]!='0')*(T[i-1]==S[i-1])+1}), dp[i][2]=min({dp[i-1][0]+(S[i]!=T[i])*(T[i-1]=='0'), dp[i-1][1]+(S[i]!=T[i])*(T[i-1]=='1'), dp[i-1][2]+(S[i]!=T[i])*(S[i-1]==T[i-1])}); printf("%d\n", min({dp[n][0], dp[n][1], dp[n][2]})); }
本文作者:Jimmy-LEEE
本文链接:https://www.cnblogs.com/redacted-area/p/18379537
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步