Codeforces Gym 101173 K. Key Knocking (构造)

来源:互联网 发布:考勤机怎么恢复数据 编辑:程序博客网 时间:2024/06/05 17:40

题意

对于给定的长为 3×N 的 01 字符串 S,求在最多变换 N 次下使得字符串 S 的 weight >= 2n

字符串的 weight 为 相邻不同字符的个数 + 1. 如 011010100 的 weight = 7

单次变换为选择连续的两个数,将 01 以及 10

解题思路

构造,对于前 3×(N1) 个字符最多变换 N-1 次已经满足 2×(N1) 的前提下,考虑最后的三个 01 字符,需在最多一次转换下获得对 weight +2 的贡献。

3×(N1) 的结束字符为 0 时:

  • 0|000 -> 0|110
  • 0|001 -> 0|010
  • 0|011 -> 0|101
  • 0|111 -> 0|110

其余组合可不变换。当 3×(N1) 的结束字符为 1 时,类似。

代码

#include<bits/stdc++.h>using namespace std;const int BASE = '0'+'1';const int N = 100000 + 10;int n;char s[N * 3];vector<int> v;inline void rev(int pos) { s[pos] = BASE - s[pos];  s[pos-1] = BASE - s[pos-1]; }bool initJug() {    int ret = 1;    for(int i=1;i<n;i++)        if(s[i] != s[i-1])  ret++;    return ret >= n/3*2 ? true : false;}bool jug(int start){    int ret = 0;    for(int i=start;i<start+3;i++)        if(s[i] != s[i-1])  ret++;    return ret >= 2 ? true : false;}void solve(int start){    if(jug(start))  return;    rev(start+1);    if(jug(start)) {        v.push_back(start+1);        return;    }    rev(start+1),   rev(start+2);    v.push_back(start+2);}int main(){    while(scanf(" %s", s)!=EOF)    {        v.clear();        n = strlen(s);        if(initJug())   {   printf("0\n");  continue;   }        if(s[0] == s[1] && s[1] == s[2])    rev(2), v.push_back(2);        for(int i=3;i<n;i+=3)            solve(i);        printf("%d\n", v.size());        for(int i=0;i<v.size();i++)            printf("%d%c", v[i], i==v.size()-1 ? '\n' : ' ');    }}
原创粉丝点击