总时间限制: 1000ms 内存限制: 1024kB
描述
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。
然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。
当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。
输入
两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。
输出
至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。
样例输入
011
000
样例输出
1
啊啊啊在11:00pm前两分钟AC了,好开心啊可以不用熬夜了,编程能力不好的我折腾一晚上了,一直在找错,一个很好的检查哪一步错误的办法是输出中间结果。我知道我的代码有点啰嗦,按不按第一个锁两种情况很多代码类似,但是我合并不好。
还有,要重视位运算。晚安~
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int setbit(int &n,int i,int v){//将n的第i位设置为v
if(v) n|=(1<<i);
else n&=~(1<<i);
}
int getbit(int n,int i){//取出n的第i位
return (n>>i)&1;
}
int flipbit(int &n,int i){//将n的第i位取反
n^=(1<<i);
}
int orilock=0;//原始锁开关情况
int lock=0;//过程中锁开关情况
int result=0; //结果锁开关情况
int main(){
char line[40];
cin>>line;
int times1=0,times2=0;
int mintimes=0;
int n=strlen(line);
for(int i=0;i<n;++i)
setbit(orilock,i,line[i]-'0');//将原始情况存入
cin>>line;
for(int i=0;i<n;++i)
setbit(result,i,line[i]-'0');//将结果存入
for(int p=0;p<2;p++){//枚举第一个密码按还是不按
lock=orilock;//按下第一个锁
if(!p){//按下第一个
times1++;
flipbit(lock,0);
flipbit(lock,1);
for(int i=1;i<n;i++){
if(getbit(lock,i-1)!=getbit(result,i-1)){
times1++;
flipbit(lock,i-1);
flipbit(lock,i);
if(i<n-1)
flipbit(lock,i+1);
}
}
if(lock!= result)
times1=100;
}
else if(p){//不按第一个
for(int i=1;i<n;i++)
if(getbit(lock,i-1) !=getbit(result,i-1)){
times2++;
flipbit(lock,i-1);
flipbit(lock,i);
if(i<n-1)
flipbit(lock,i+1);
}
if(lock!= result)
times2=100;
}
}
mintimes=min(times1,times2);
if(mintimes==100){
cout<<"impossible"<<endl;
return 0;
}
cout<<mintimes<<endl;
return 0;
}