openjudge 8469 特殊密码锁

总时间限制: 1000ms 内存限制: 1024kB
描述
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。

然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。

当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。

输入
两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。
输出
至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。
样例输入
011
000
样例输出
1

思路
在对于x[i],y[i]两个位置时,我们总是用更改以x[i+1]为核心的组合,即一般情况下,更改x[i],x[i+1],x[i+2],保证x[i]前的已经相同的位置不受影响;for(范围为第一个到倒数第二个)一边后,比较最后一位相同;
x[1]表示第一位数字,但在下述代码中,x[0]存储的才是第一位数字。
但对于x[1]
如果x[1]与y[1]不同,有两种选择,
预先更改以x[1]为核心的x[1]x[2]
或更改以x[2]为核心的x[1]x[2]x[3];
这样,我们就有了两种不同的选择,分别进行操作,求取较小答案或唯一答案;
如果x[1]与y[1]相同,我们也有两种选择,
保持x[1]不变,
或,更改以x[1]为核心的x[1]x[2],对于已经被改的不同的x[1],我们完全可以在更改以x[2]为核心时,再度改回原状态 如0001 0000;

综上,无论x[1]是否相等,我们都有两种选择:更改以x[1]为核心的组合或更改以x[2]为核心的组合,两个结果求min或求唯一值;

注意:
不能 只判断x[1]不相等 才更改以x[1]为核心的组合。
如果酱的话,那么0001 0000 就会输出impossible而非正确答案3

#include
#include
#include
#include
#include
const int N=3000+20;
using namespace std;
int tot,ans1=0,ans2=0,len;
char a[N],b[N];
int x[N],y[N];
void init(){
    tot=0;
        for(int i=0;i48;
            y[i]=b[i]-48;   
        }
}
int main(){
    scanf("%s",a);
    gets(b);
    scanf("%s",b);
    len=strlen(a);
        init();
        tot++;
        x[0]=x[0]^1;
        x[1]=x[1]^1;
        for(int i=0;i1;i++){
            if(x[i]!=y[i]){
                tot++;
                x[i]^=1;
                x[i+1]^=1;
                x[i+2]^=1;
            }
        }
        if(x[len-1]==y[len-1]) ans1=tot;
        init();
        for(int i=0;i1;i++){
            if(x[i]!=y[i]){
                tot++;
                x[i]^=1;
                x[i+1]^=1;
                x[i+2]^=1;
            }
        }
        if(x[len-1]==y[len-1]) ans2=tot;
    if(!ans1&&!ans2) printf("impossible");
    else if(!ans1||!ans2) printf("%d",max(ans1,ans2));
    else printf("%d",min(ans1,ans2));
    return 0;
}

你可能感兴趣的:(贪心)