描述
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。
然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。
当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。
输入
两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。
输出
至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。
样例输入
011
000
样例输出
1
题目分析:
这道题我们可以遍历整个密码锁,让原始串与答案串一一比较,如果两串当前位不一样则反转下一位的按钮,遍历完成后如果最后最后一位与答案串不同,则无法实现转变输出impossible,否则输出记录的改变次数。
要注意一点:要把第一位是否反转的两种情况都试一次。
1.从第1位开始,如果第一位不匹配则反转第二位,以此类推。
2.先反转第1位,再开始一一比较。
上代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <set>
#include <queue>
#include <vector>
#include <string>
#include <cstring>
#include <sstream>
#include <algorithm>
#define LL long long
using namespace std;
const int N=35;
int cnt=0;
char e[N];
void mswap(char &c) //反转函数
{
if(c=='1') c='0';
else c='1';
}
bool sol(char s[],int len)
{
int i=1;
while(s[i]!='\0')
{
if(s[i-1]!=e[i-1]) //如果第i-1位不同,反转下一位
{
mswap(s[i-1]);
mswap(s[i]);
if(i+1<len) mswap(s[i+1]);
cnt++;
}
i++;
}
if(s[len-1]==e[len-1]) return true;
else return false;
}
int main()
{
char s[N],str[N];
cin>>s>>e;
memcpy(str,s,sizeof s); //将s备份
int len=strlen(s);
int ans=1e9;
if(sol(s,len)) ans=cnt; //第一种情况
cnt=1;
mswap(str[0]); //第二种情况
if(1<len) mswap(str[1]);
if(sol(str,len)) ans=min(ans,cnt);
if(ans>=1e9) puts("impossible");
else cout<<ans<<endl;
return 0;
}