转载自:http://blog.csdn.net/lyhypacm/article/details/5813634
DES:相邻的两盏灯状态可以互换,给出初始状态。询问是否能在三步之内到达。如果能的话。输出不属。超出3步就输出more。
貌似典型应用是位压缩。我觉得各种按位运算用的也很巧妙。判断两盏灯是不是状态一样的时候,和交换状态的时候。先广搜一遍,保存到达各种状态的最短路径,然后查询就可以了。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<string> 6 #include<queue> 7 using namespace std; 8 const int maxn=1<<16; 9 10 int visi[maxn]; 11 //两点相连,一共有32条边 12 int a[32][2]={{1,2},{3,4},{5,6},{7,8},{9,10},{11,12},{13,14},{15,16},{1,3},{2,4},{5,7},{6,8},{9,11},{10,12},{13,15},{14,16}, 13 {1,5},{2,6},{3,7},{4,8},{9,13},{10,14},{11,15},{12,16},{1,9},{2,10},{3,11},{4,12},{5,13},{6,14},{7,15},{8,16}}; 14 15 void BFS(int p) 16 { 17 int i; 18 visi[p]=0; 19 queue <int> mq; 20 mq.push(p); 21 while(!mq.empty()) 22 { 23 int t=mq.front(); 24 mq.pop(); 25 if(visi[t]>=3) continue; 26 for(i=0;i<32;i++) //看下可以改变哪两个点 27 { 28 int p1,p2; 29 //表示a[i]灯的状态 30 p1=t&(1<<(a[i][0]-1)); 31 p2=t&(1<<(a[i][1]-1)); 32 if(p1==p2 || p1&&p2) continue; //两个灯状态一样 33 p1=t^(1<<(a[i][0]-1)); 34 p2=p1^(1<<(a[i][1]-1)); //两个灯交换状态 35 if(visi[p2]==-1) //如果是其它的值,说明此时步骤不是最小的 36 { 37 mq.push(p2); 38 visi[p2]=visi[t]+1; 39 } 40 } 41 } 42 } 43 44 int main() 45 { 46 int tes; 47 int x,i,j; 48 x=(1<<16)-(1<<8); //就是最终状态作为起始状态 49 memset(visi,-1,sizeof(visi)); 50 BFS(x); 51 scanf("%d",&tes); 52 for(i=1;i<=tes;i++) 53 { 54 int sum=0; //表示状态 55 for(j=0;j<16;j++) 56 { 57 int tmp; 58 scanf("%d",&tmp); 59 if(tmp==1) 60 sum+=1<<j; 61 } 62 63 printf("Case #%d: ",i); 64 if(visi[sum]==-1) //表示三步之内没达到 65 puts("more"); 66 else printf("%d\n",visi[sum]); 67 } 68 return 0; 69 }