POJ 1754
Program links: http://poj.org/problem?id=1753
The purpose of writing this blog is to make me remember the bitwise operation.
符号 | 描述 | 运算规则 |
---|---|---|
& | 与 | 两个位都为1时,结果才为1 |
| | 或 | 两个位都为0时,结果才为0 |
^ | 异或 | 两个位相同为0,相异为1 |
~ | 取反 | 0变1,1变0 |
<< | 左移 | 各二进位全部左移若干位,高位丢弃,低位补0 |
>> | 右移 | 各二进位全部右移若干位,对无符号数,高位补0,有符号数,各编译器处理方法不一样,有的补符号位(算术右移),有的补0(逻辑右移) |
eg:
- 判断右起第i位是不是1:
(x >> (i - 1)) == 1
- 右数第k位取反:
x ^ (1 << (k - 1))
附上大牛的位运算详解:
http://blog.csdn.net/morewindows/article/details/7354571
http://www.matrix67.com/blog/archives/263
这题题意大概是选一个把它的上下左右(如果有)和自己翻一下
因为只有两个状态所以选择了二进制然后用位运算
比较坑爹的地方在于不好模拟,这里给出样例的模拟:
1001 1101 1001 1000
0101 0101 1001 1000
1011 0001 1001 1000
1111 1111 1101 1000
1111 1111 1111 1111
4次
顺便我在代码里加上了last数组用来查看结果是怎么得到的,方便得知程序是否正确,代码如下:
c++
#include <iostream>
#include <queue>
using namespace std;
int main()
{
int k = 0;
char c;
for (int i = 0; i < 16; i++) {
cin >> c;
if (c == 'b')
k = k * 2 + 1;
else if (c == 'w')
k = k * 2;
}
if (k == 0 || k == ((1 << 16) - 1)) {
cout << "0" << endl;
return 0;
}
queue <int> t, m;
bool a[1 << 16] = { 0 };
int last[1 << 16] = { 0 };
t.push(0);
m.push(k);
a[k] = 1;
while (!t.empty()) {
for (int i = 15; i >= 0; i--) {
k = m.front() ^ (1 << i);
if (i + 4 < 16)
k = k ^ (1 << (i + 4));
if (i - 4 >= 0)
k = k ^ (1 << (i - 4));
if (i % 4 != 0)
if (i != 0)
k = k ^ (1 << (i - 1));
if ((i + 1) % 4 != 0)
if (i != 15)
k = k ^ (1 << (i + 1));
if ((k == 0) || (k == ((1 << 16) - 1))) {
cout << t.front() + 1 << endl;
return 0;
}
if (!a[k]) {
t.push(t.front() + 1);
m.push(k);
a[k] = 1;
last[k] = m.front();
}
}
t.pop();
m.pop();
}
cout << "Impossible" << endl;
return 0;
}
顺便一提:markdown里面的>>是这么打出来的“& g t ; & g t ;”(空格和引号自己去掉)