Gym101845 B.Binary Strings

http://codeforces.com/group/NVaJtLaLjS/contest/241861/problem/B
Felipe has a binary string A of length n (1 ≤ n ≤ 5000) which he wants to transform into string B (of length n as well) using a series of operations. He can use the following operations:

  • Operation 1: He can move the last element of A to the front. For example, 01001 would become 10100.

  • Operation 2: He can take any two consecutive elements and flip them. A flip turns a 1 into a 0 and a 0 into a 1. For example, if he applies this operation to the first two elements of 10100, it would become 01100.

Felipe actually doesn’t like operation 2, so he wants to use it as few times as possible. Given A and B find the minimum number of operations type 2 needed to transform A into B, or say if it’s impossible.

Input
Input consist of two lines with binary strings A and B, respectively.

It is guaranteed that both strings have the same length.

Output
Print one single line with the minimum number of operations type 2 needed to transform A into B. or  - 1 if it’s impossible to do so.

Examples
inputCopy
01001
01010
outputCopy
0
inputCopy
11111
00000
outputCopy
-1
inputCopy
001010
100001
outputCopy
1

题意:有等长的两字符串s,t。由两个操作来把s变成t,①把s的最后一个字符移到最前面②选出两个相邻的字符,每个字符取反。要求尽量少用操作2。
思路:考虑操作1,它的作用是什么?有两个作用,一是循环移位,把s变到一个理想的姿势,从而尽量少用操作2然后与t相同,二是使得s的首末字符可以使用操作2。
那么我们把s扩大一倍,即ss,枚举每相邻的n个字符,然后暴力匹配,只要当前s[i],t[i]不一样就使用操作2,如果最后一个字符相同,那么可行,与ans比较,取最小值。 因为这个过程中漏掉了【首末字符可以取反】,所以把首末字符取反再做一遍
因为操作1只有那两个用处,所以说,如果存在移位->取反->移位->取反->移位…这样的操作,实际上,只要突出理想姿势+首末可以取反就可以了。
实际上我自己也还是不大理解

#include<bits/stdc++.h>
using namespace std;
#define maxn 10000+100

int n,ans=(1<<30);
char s[maxn],t[maxn];

void check(char *s,int flip)
{
    int ret=flip;
    for(int i=0;i<n-1;i++)
    {
        if(s[i]!=t[i])ret++,s[i]='1'-(s[i]-'0'),s[i+1]='1'-(s[i+1]-'0');
    }
    if(s[n-1]==t[n-1])ans=min(ans,ret);
}

int main()
{
    //freopen("input.in","r",stdin);
    scanf("%s%s",s,t);
    n=strlen(s);
    int num1=0,num2=0;
    for(int i=0;i<n;i++)num1+=s[i]-'0',num2+=t[i]-'0';
    if(abs(num1-num2)&1){cout<<-1<<endl;exit(0);}
    for(int i=0;i<n;i++)s[i+n]=s[i];
    for(int i=0;i<n;i++)
    {
        char b[maxn];
        memcpy(b,s+i,sizeof(char)*n);
        check(b,0);
        memcpy(b,s+i,sizeof(char)*n);
        b[0]='1'-(b[0]-'0');b[n-1]='1'-(b[n-1]-'0');
        check(b,1);
    }
    cout<<ans<<endl;
}
全部评论

相关推荐

不愿透露姓名的神秘牛友
07-24 13:39
在记录秋招的大魔王很...:别被忽悠了,我做了多年销售。我可以告诉你,这就是忽悠你的,销售一定要看底薪也要看提成两者不可缺一。提成是有业绩的时候才拿的到的,谁能保证一直有单状态都好。销售有时候很讲究运气的。底薪是你这个人这个岗位日常工作体现的价值。别小看底薪,你看那些跳槽去做经理主管的,底薪底一些,人家愿意去吗?所以那些说销售靠提成的纯属忽悠,除非他们的业务很容易成单。
点赞 评论 收藏
分享
06-20 17:42
东华大学 Java
凉风落木楚山秋:要是在2015,你这简历还可以月入十万,可惜现在是2025,已经跟不上版本了
我的简历长这样
点赞 评论 收藏
分享
06-08 22:25
门头沟学院 Java
从零开始的转码生活:这hr不会打开手机不分青红皂白给所有人群发这句话,过一会再给所有人再发一遍,这肯定会有重复的,不管,再过一会再发一遍
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务