您的位置:首页 > 其它

GYM 101173 K.Key Knocking(构造)

2017-03-20 16:06 423 查看
Description

一个长度为3*n的01串,每次可以翻转连续的两个字符,要求至多翻转n次使得这个3*n的串至少有2*n个连续的段且相邻两端不一样(就是连续的0算一段,然后连续的1,…)

Input

一个长度为3*n的01串(1<=n<=1e5)

Output

首先输出最少操作数,之后输出每次操作的位置(一次翻转的位置是该次翻转的连续两个字符的第一个编号)

Sample Input

000000000

Sample Output

3

2 5 6

Solution

每三个一组,只要能把每组分成两段而且和前面的不连着最后段数一定不小于2*n,例如前一个是1(0同理),当前组只有八种情况(冒号前表示操作前状态,冒号后表示操作后的状态):

000:011

001:001

010:010

011:011

100:010

101:101

110:101

111:001

故每种情况至多操作一次即可,扫一遍即得到操作位置

Code

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: