特殊密码锁

总时间限制: 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;
}

猜你喜欢

转载自blog.csdn.net/qq_40486952/article/details/84112348