一道需要活躍思維的搜索題,當然,對於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;
}