1. 程式人生 > >GYM 101173 K.Key Knocking(構造)

GYM 101173 K.Key Knocking(構造)

tdi 要求 using fine time .net ios ble sin

原題鏈接

參考自

問題描述:一個長度為3*n的01串,每次可以翻轉連續的兩個字符,要求至多翻轉n次使得這個3*n的串至少有2*n個連續的段且相鄰兩端不一樣(就是連續的0算一段,然後連續的1,…)

解法:每三個一組,只要能把每組分成兩段而且和前面的不連著最後段數一定不小於2*n,例如前一個是1(0同理),當前組只有八種情況(冒號前表示操作前狀態,冒號後表示操作後的狀態):
000:011
001:001
010:010
011:011
100:010
101:101
110:101
111:001
故每種情況至多操作一次即可,掃一遍即得到操作位置

#include<cstdio>
#include
<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<vector> #include<queue> #include<map> #include<set> #include<ctime> using namespace std; typedef long long ll; #define INF 0x3f3f3f3f #define maxn 111111 char s[maxn*3
]; int ans[maxn],res; int main() { while(~scanf("%s",s+1)) { s[0]=0; int n=strlen(s+1); res=0; for(int i=1;i+2<=n;i+=3) { int a=s[i]-0,b=s[i+1]-0,c=s[i+2]-0; if(s[i-1]==0) { if(a==0
&&b==0&&c==0)ans[res++]=i; else if(a==0&&b==0&&c==1)ans[res++]=i+1,s[i+2]=0; else if(a==0&&b==1&&c==1)ans[res++]=i; else if(a==1&&b==1&&c==1)ans[res++]=i+1,s[i+2]=0; } else { if(a==0&&b==0&&c==0)ans[res++]=i+1,s[i+2]=1; else if(a==1&&b==0&&c==0)ans[res++]=i; else if(a==1&&b==1&&c==0)ans[res++]=i+1,s[i+2]=1; else if(a==1&&b==1&&c==1)ans[res++]=i; } } printf("%d\n",res); for(int i=0;i<res;i++)printf("%d%c",ans[i],i==res-1?\n: ); } return 0; }

GYM 101173 K.Key Knocking(構造)