GYM 101173 K.Key Knocking(构造)

本文介绍了一个关于3n长度01串的翻转问题,目标是在至多翻转n次的情况下,使串中至少有2n个不相连的连续相同字符段。通过分析每三个字符为一组的情况,提出了一种有效的解决方法,并给出了具体的实现代码。

原题链接

 

参考自

 

问题描述:一个长度为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;
}

 

转载于:https://www.cnblogs.com/fht-litost/p/7267098.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值