1. 程式人生 > >特殊密碼鎖

特殊密碼鎖

總時間限制: 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;
}