您的位置:首页 > 其它

poj1753 Flip Game

2016-05-27 15:38 302 查看
http://poj.org/problem?id=1753

位压缩,广度优先搜索

异或运算的用途之一:使某些特定的位翻转,例如对数10100001的第2位和第3位翻转,则可以将该数与00000110进行按位异或运算。 10100001^00000110 = 10100111

将当前棋局状态拟化为一个二进制数,比如:

w w w w

w w w w

w w w w

w w w w

就是0000 0000 0000 0000。比如现在要翻转左上角的那个棋,那么它的右边和下边也要翻转。也就是0000 0000 0000 0000需要变成1100 1000 0000 0000。通过0000 0000 0000 0000^1100 1000 0000 0000即可实现。

现在翻转操作有16种可能情况,需要16个数与当前状态数异或。它们分别为0x1100 1000 0000 0000... ...

化为十进制数分别为: 51200 ... ...

广度优先搜索:当前状态数有16种操作可能,每种操作之后新状态数又对应16种操作可能,中间可能会出现状态数重复的现象,新状态数为0000 0000 0000 0000或者1111 1111 1111 1111 停止。。。

#include <stdio.h>
#include <string.h>
int visited[65535],queue[65535];
int change[16]=
{51200,58368,29184,12544,
35968,20032,10016,4880,
2248, 1252, 626,  305,
140,  78,   39,   19};
int Breadth_FirstSearch(int state)
{
int front,rear;//头指针指示器,尾指针指示器
int x,temp,i;
if(state==0||state==0xffff)
return 0;
memset(visited,-1,sizeof(visited));//-1表示没被访问,>-1表示访问过了。
visited[state]=0;
front=rear=0;//初始化空队
queue[rear++]=state;//state入队
while(front!=rear)
{
x=queue[front++];//队头元素出队
for(i=0;i<16;i++)
{
temp=x^change[i];//新的状态
if(temp==0||temp==0xffff)//END
return visited[x]+1;
if(visited[temp]==-1)
{
visited[temp]=visited[x]+1;
queue[rear++]=temp;
}
}
}
return -1;
}
int main()
{
int i,j,s=0;
char str[5];
for(i=0;i<4;i++)//输入完,得到当前状态s
{
scanf("%s",str);
for(j=0;j<4;j++)
{
s<<=1;
if(str[j]=='b')
s++;
}
}
if(Breadth_FirstSearch(s)!=-1)
printf("%d\n",Breadth_FirstSearch(s));
else
printf("Impossible\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: