一道需要活跃思维的搜索题,当然,对于2^16 的复杂度也可以枚举来做.
题目大意: http://poj.grids.cn/practice/1753/
给一个4*4的棋盘,上面有黑子 (用字符'b'表示) 和白子 (用字符'w'表示) .可以选择棋子翻转,每翻转一个棋子,其周围四个棋子也会被翻转(边角情况正常处理),问最少翻转多少次可以让棋盘全黑或全白.
解题思路:
一看只有16个格子,首先想到了枚举~:
for(int i=0;i<1;++i)
.
.
.
16层......后来一想这么写多丢人......所以还是搜索吧,bfs和dfs基本都没有问题,因为求最少步数,所以还是bfs比较适合.
把棋盘看做简单的0-1矩阵,对每一个位置取反时也会对周围4个位置取反,对一个数取反可以写做: n=n^1; .那么从什么状态开始搜素呢?~
将0-1矩阵合并,看成一个二进制数,那么他的范围仅仅为 0-0xffff 也就是一共仅有 0xfff 种状态.对每一位翻转,可以求出其状态转移方程:
当前状态a ^ 转移状态i (i为翻转的位置),a==0 时结束,每个位置会有其单独的翻转状态.比如 0,0 位:
1100
1000
0000
0000 周围四个位置取反.
接下来就是么每一位的转移状态i的处理. 将矩阵每一位编号.
F E D C
B A 9 8
7 6 5 4
3 2 1 0
那么,其上下左右就为: 上: -4 下:+4 左:-1 右: +1 求转移状态的源码就为:
void build() {
memset(no,0,sizeof(no));
int num=1;
for(int i=N;i>0;--i) {
for(int j=1;j<=4;++j) {
int tx=i*4-j;
no[num]=1<<(tx);
for(int k=0;k<4;++k) {
int x=tx+dbit[k];
if(x<0||x>15)
continue;
if((tx+4)%4==0&&(x+4)%4==3) {
continue;
}
if((tx+4)%4==3&&(x+4)%4==0) {
continue;
}
no[num]=no[num]+(1<<x);
}
num++;
}
}
}
求出转移状态后,就以每一个点为起点bfs 即可:
#include <myhead.h>
const int N=4;
const int s=0xffff;
const int t=0;
const int dbit[]={-4,1,+4,-1};
struct Node {
int m,num;
int i;
};
bool _hash[100000];
char a[N+1][N+1];
int no[20];
Node node;
void build() {
memset(no,0,sizeof(no));
int num=1;
for(int i=N;i>0;--i) {
for(int j=1;j<=4;++j) {
int tx=i*4-j;
no[num]=1<<(tx);
for(int k=0;k<4;++k) {
int x=tx+dbit[k];
if(x<0||x>15)
continue;
if((tx+4)%4==0&&(x+4)%4==3) {
continue;
}
if((tx+4)%4==3&&(x+4)%4==0) {
continue;
}
no[num]=no[num]+(1<<x);
}
num++;
}
}
}
bool init() {
for(int i=0;i<N;++i) {
if(scanf("%s",a[i])==EOF) {
return false;
}
}
memset(_hash,0,sizeof(_hash));
node.i=node.m=node.num=0;
int m=0;
for(int i=N-1;i>=0;--i) {
for(int j=N-1;j>=0;--j) {
if(a[i][j]=='b') {
node.m=node.m+(1<<m);
}
m=m+1;
}
}
return true;
}
void bfs() {
queue<Node> q;
q.push(node);
while(!q.empty()) {
Node tmp=q.front();
q.pop();
if(tmp.m==s||tmp.m==0) {
printf("%d\n",tmp.num);
return ;
}
node.num=tmp.num+1;
for(int i=1;i<=16;++i) {
if(tmp.i!=i) {
node.i=i;
node.m=(tmp.m^no[i]);
if(!_hash[node.m]) {
_hash[node.m]=true;
q.push(node);
}
}
}
}
printf("Impossible");
}
int main()
{
build();
init();
bfs();
return 0;
}