poj 2965 The Pilots Brothers' refrigerator枚举(bfs+位运算)

poj 2965 The Pilots Brothers' refrigerator枚举(bfs+位运算)

//题目:http://poj.org/problem?id=2965
//题意:电冰箱有16个把手,每个把手两种状态(开‘-’或关‘+’),只有在所有把手都打开时,门才开,输入数据是个4*4的矩阵,因此考虑用位表示。可以改变任
意一个把手的位置,但同时改变其所在的行和列。求最小步骤.
//耗时 800MS
1
#include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<queue> 5 6 using namespace std; 7 int id,vis[1<<17]; 8 int a[1<<17],b[1<<17],before[1<<17]; 9 int p[16]={4383, 8751, 17487, 34959, 4593, 8946, 17652, 35064, 7953, 12066, 10 20292, 36744, 61713, 61986, 62532, 63624}; 11 struct node 12 { 13 int x,step; 14 }; 15 16 void hui(int x) 17 { 18 if(x!=id) 19 { 20 hui(before[x]); 21 printf("%d %d ",a[x],b[x]); 22 } 23 }; 24 25 void bfs() 26 { 27 queue<node>q; 28 int i; 29 struct node cur,next; 30 next.step=0; next.x=id; 31 q.push(next); 32 memset(vis,0,sizeof(vis)); 33 vis[next.x]=1; 34 35 while(!q.empty()) 36 { 37 cur=q.front(); 38 q.pop(); 39 for(i=0; i<16; i++) 40 { 41 next.x=cur.x^p[i]; 42 next.step=cur.step+1; 43 44 if(vis[next.x]==0) 45 { 46 before[next.x]=cur.x; 47 a[next.x]=4-(i/4); 48 b[next.x]=4-(i%4); 49 50 vis[next.x]=1; 51 q.push(next); 52 if(next.x==0) 53 { 54 printf("%d ",next.step); 55 hui(next.x); 56 } 57 } 58 } 59 } 60 }; 61 62 int main() 63 { 64 int i,j; 65 char c; 66 id=0; 67 for(i=0; i<4; i++) 68 { 69 for(j=0; j<4; j++) 70 { 71 id<<=1; 72 scanf("%c",&c); 73 if(c=='+') 74 id+=1; 75 } 76 getchar(); 77 } 78 bfs(); 79 return 0; 80 }

  bfs用 before数组 来回溯改变的点的坐标。

不过耗时太多,这题用 dfs更好,因为要求输出翻转过程。

DFS可以看一下:http://blog.csdn.net/lyy289065406/article/details/6642597这个博客代码跑时较少