OpenJudge 8469: 特殊密码锁
描述
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。
输入
两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。
输出
至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。
样例输入
011
000
样例输出
1
思路
贪心
一个灯如果按了第二下,就会抵消上一次按下所产生的影响。
因此,一个灯只有按或者不按两种情况,不存在一个灯要开关多次的情况。
例如八个灯 00000000
按1后 11000000
按3后 10110000
按1后 01110000
这和八个灯 00000000
只按一次3后 01110000
是完全相同的情况我们只需要考虑是否按下第一个灯。因为如果第一个灯的状态被确定了,那么是否按下第二个灯也就决定了(如果第一个灯与期望不同,则按下,如果期望相同,则不按下)同理,第三个灯是否按下也唯一确定。所以,本题只要分两种情况:灯1被按下和没有被按下之后使用for循环判断别的灯是否需要按下即可当循环结束,若现在的灯况与答案相同,则输出两种方案中按键次数最少的,若不同,则impossible!
源代码
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
string lockin,lockout;
int L1[35],L2[35],L3[35];
int main(){
int num1=0,num2=0;
cin>>lockin>>lockout;
int len=lockin.length();
for(int i=0;i<len;i++){
L1[i]=(int)(lockin[i]-'0');
L3[i]=L1[i];
L2[i]=(int)(lockout[i]-'0');
}
//不按第一把锁
for(int i=1;i<len;i++){
if(L1[i-1]!=L2[i-1]){
num1++;
L1[i-1]^=1;
L1[i]^=1;
L1[i+1]^=1;
}
}
//按第一把锁
L3[0]^=1;
L3[1]^=1;
num2++;
for(int i=1;i<len;i++){
if(L3[i-1]!=L2[i-1]){
num2++;
L3[i-1]^=1;
L3[i]^=1;
L3[i+1]^=1;
}
}
int flag1=1,flag2=1;
for(int i=0;i<len;i++){
if(L1[i]!=L2[i]){
flag1=-1;
}
if(L3[i]!=L2[i]){
flag2=-1;
}
}
if(flag1==-1 && flag2==-1){
cout<<"impossible"<<endl;
}
else if(flag1==1 && flag2==1){
int num=min(num1,num2);
cout<<num<<endl;
}
else{
if(flag1==1) cout<<num1<<endl;
if(flag2==1) cout<<num2<<endl;
}
return 0;
}
参考:
http://www.cnblogs.com/BobHuang/p/7191791.html
http://blog.youkuaiyun.com/mading0613/article/details/54881885