-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path特殊密码锁
98 lines (80 loc) · 2.91 KB
/
特殊密码锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
OpenJudge全局题号 8469 【不大明白题目的意思为什么要说两行, 两行是分开写其实也属于一个密码锁? 如果是这样 那code说得通】
- 描述
有一种特殊的二进制密码锁,由n个相连的按钮组成(n<30),按钮有凹/凸两种状态,用手按按钮会改变其状态。
然而让人头疼的是,当你按一个按钮时,跟它相邻的两个按钮状态也会反转。当然,如果你按的是最左或者最右边的按钮,该按钮只会影响到跟它相邻的一个按钮。
当前密码锁状态已知,需要解决的问题是,你至少需要按多少次按钮,才能将密码锁转变为所期望的目标状态。
- 输入
两行,给出两个由0、1组成的等长字符串,表示当前/目标密码锁状态,其中0代表凹,1代表凸。
- 输出
至少需要进行的按按钮操作次数,如果无法实现转变,则输出impossible。
- 样例输入
011
000
- 样例输出
1
bl8469 特殊密码锁
By Guo Wei
*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
//枚举第一个按钮是否按下的两种情况即可。对于指定的一种情况,后面的事情都是确定的
//这里相当于把某一行的每一列当做熄灯例题中的一行, 每一位的操作都确保前一位是熄灭的, 所以操作是确定的)
int oriLock;
int lock;
int destLock;
void SetBit(int &c, int j, int v){
if(v){//v = 1
c |= (1<<j);
}
else{ //v = 0
c &= ~(1<<j);
}
}
void FlipBit(int &c, int j){
c ^= (1<<j);
}
int GetBit(int c, int j){
return (c>>j)&1;
}
int main()
{
char line[40];
destLock = lock = oriLock = 0;
cin >> line;
int N = strlen(line);
for(int i = 0; i < N; ++i)
SetBit(oriLock,i, line[i] - '0'); //line 1
cin >> line;//line 2 //也可以按照例题中一个一个输入数字 //line 2 表示目标状态!
for(int i = 0; line[i]; ++i)//这边也应该可以写 i < N, line[i]表示 line 的 i位上有值则运行for循环
SetBit(destLock,i, line[i] - '0');
int minTimes = 1 << 30; (最多的尝试的次数)
for(int p = 0; p < 2; ++p) { //p代表最左边按钮
lock = oriLock; //新的方案, 重新赋值开始
int times = 0;
int curButton = p; //一开始尝试, p可按下 可不按, 共两种方案
for(int i = 0; i < N; ++i) {
if(curButton) { // == 1 -> need to be pressed
++ times;
if( i > 0) //has left
FlipBit(lock,i-1);
FlipBit(lock,i);
if( i < N-1) //has right
FlipBit(lock,i+1);
}
if( GetBit(lock,i) != GetBit(destLock,i)) //当前位置与目标是否一致, 不一致则current表示按下, 则处理下一位时, 可使当前为状态与目标一致
curButton = 1;
else
curButton = 0;
} //处理完一行后比较 与dest是否一致
if( lock == destLock)
minTimes = min(minTimes ,times);
}
if( minTimes == 1 << 30)
cout << "impossible" << endl;
else
cout << minTimes << endl;
return 0;
}