特殊密码锁 题解
题目地址:特殊密码锁
样例输入
011
000
样例输出
1
这道题与熄灯问题很类似。有过熄灯问题解决经验的应该会很快得出思路来。
这道题用枚举的方法来求解,你问我怎么知道的,因为这是我学习枚举算法的课后习题【滑稽.jpg】。
要明白的是,每一位数字可以被它的前一位,它本身位置,还有它后面那位给改变。而且每个位置的按钮最多按1次,因为按2次就和按0次是一样的效果。
拿样例1来举例说明。初始状态为011。当按下从左往右数第一位按钮时,状态就会变为101,这时观察第一位为1与最终状态0不符合,就可以按下第2位来改变第1位的状态。然后这时的状态为010。这样,第1位改变状态的机会全部用完了,而第1位也变为了最终状态0。接下来第2位与最终状态不符合,那么就按下第3位的按钮,此时状态变为了001。至此,第1,2位的状态与最终状态全部符合。第3位状态不符合,怎么办?我们已经没有改变状态的机会了(按按钮的机会)。这就说明,刚开始按下第一个按钮是错误的。
重新来过罢。
这次第1位的按钮不要按,那么来到第2个按钮,那么观察到第1位与最终状态符合,那么就不按下第2个按钮。可能有人疑惑了,第2个的状态还与最终不符合。我们不管他,因为第3个按钮还能改变第2位的状态。接着按下第3个按钮,最终状态变为000,完全符合!
你可能观察出了,也可能没观察出来。
这道题求解思路就是,假设第1个按钮为按下或者不按下。之后的第2个按钮开始,再根据前一个按钮的状态来决定是否按下。到了最后一个按钮按完之后,我们已经确保了除了最后一个位置以外其他状态都已经与最终状态相符了。这时检查最后一个状态是否与最终状态相符就能确定我们的结果是否正确。
Then show the code.
#include <cstdio>
#include <cstring>
#include <memory.h>
#define INFINITY 99999
void ProcessInput(char *buff, char *temp){
int len = strlen(temp);
for(int i = 0; i < len; i++){
buff[i] = temp[i]-'0';
}
}
void SlipLock(char *buff, int i){
if(buff[i])
buff[i] = 0;
else
buff[i] = 1;
}
int main(){
//a用来存放初始状态 b是临时存放的密码锁的状态 c是最终要达到的状态
char a[32], b[32], c[32], temp1[32];
memset(a, 0, sizeof(char)*10);
memset(c, 0, sizeof(char)*10);
int count = 0, len, min = INFINITY;
//将输入拆分成1个数字 存放到每个数组元素中
scanf("%s", temp1);
ProcessInput(a, temp1);
scanf("%s", temp1);
ProcessInput(c, temp1);
len = strlen(temp1);
//k代表此时第一个按钮是否被按下,
//0为不按下 1为按下
for(int k = 0; k < 2; k++){
//初始化密码锁状态
memcpy(b, a, sizeof(char)*10);
count = 0;
if(k){
SlipLock(b, 0);
SlipLock(b, 1);
count++;
}
for(int i = 1; i<len; i++){
//如果目前的第i-1位与最终状态的i-1位不符合 那么按下按钮
if(b[i-1] != c[i-1]){
SlipLock(b, i);
if(i < len)
SlipLock(b, i+1);
count++;
}
}
//如果最后一位相同 那么说明密码锁转变成功
if(b[len-1] == c[len-1])
if(min > count)
min = count;
}
if(min == INFINITY)
printf("impossible");
else
printf("%d", min);
return 0;
}
不忘初心方得始终