poj1753(位运算(异或)+ bfs)

来源:互联网 发布:奶瓶wifi破解软件下载 编辑:程序博客网 时间:2024/05/01 21:50

        题目链接:http://poj.org/problem?id=1753

         题目大意:在一个4*4的矩阵中,由16快一面是黑色,一面是白色的圆盘组成,现在照如下操作:

           1.在16快圆盘中任选一块,

            2.翻转该块圆盘和它上下左右的圆盘

         问如何能在翻转次数最少的情况下将16快圆盘翻成全是白色或者黑色,输出最少的翻转次数,如果怎么都达不到目标,则输出“Impossible”。

             思路:第一道位运算(只要是异或来翻转圆盘)题目,总共16块圆盘,所以16个二进制位就可以了,‘1’代表白色,‘0’代表黑色,所以最终状态是:“1111 1111 1111 1111”或“0000 0000 0000 0000”即代表成功了。具体看代码,有相对详细的解释。

#include<stdio.h>#include<math.h>#include<string.h>typedef struct {int zt;int flips;} state;state q[65536];//队列int head=0,tail=-1;int flip[16]={19,39,78,140,305,626,1252,2248,4880,10016,20032,35968,12544,29184,58368,51200};/* 对应翻转: 10011 100111 1001110 10001100                              100110001 1001110010 10011100100 100011001000 1001100010000 10011100100000 100111001000000 1000110010000000 11000100000000 111001000000000 1110010000000000 1100100000000000*/int fliped[65536];//标记状态是否出现过,由于总共只有65535种状态char map[4][4];void enq(state s) //进队{++tail;         q[tail].zt=s.zt;q[tail].flips=s.flips;fliped[q[tail].zt] = 1;}void deq()//出队{   ++head;}state gethead()//取队首元素{return q[head];}int isempty()//判空{if(head>tail)return 1;else return 0;}int bfs(){   int i;   state temp,temp1;   memset(fliped,0,sizeof(fliped));   enq(q[0]);   while(!isempty())   {       temp=gethead();   deq();   if(temp.zt==0 || temp.zt == 65535)//达到了目标状态   return temp.flips;   else   {   for(i=0;i<16;i++)   {   temp1.zt =temp.zt ^ flip[i];//位异或翻转圆盘   if(!fliped[temp1.zt])//该状态没有出现过,入队,对应的翻转次数加1   {   temp1.flips=temp.flips+1;   enq(temp1);   }   }   }   }   return -1;}int main(){int i,j,minflip;int Inizt=0;for(i=0;i<4;i++)scanf("%s",map[i]);         for(i=0;i<4;i++)//求出初始状态for(j=0;j<4;j++){if(map[i][j] - 'w' == 0)Inizt+=(int)pow(2,(double)(i*4+j));}    q[0].zt=Inizt;q[0].flips=0;minflip=bfs();if(minflip == -1)printf("Impossible\n");else printf("%d\n",minflip);return 0;}


 

 

原创粉丝点击