[poj1753]Flip Game解题报告 BFS+位运算+状态压缩


题目:http://poj.org/problem?id=1753
题意:在一个4*4的方格阵里,每格里有一个一面白一面黑的棋子,初始状态由输入给出。游戏开始后,每次选择16格中的任何一个,然后将它以及它周围紧相邻的4个棋子翻转(超出边缘的不计)。游戏的目的是将所有色块翻成同一种颜色。问能不能达到游戏目的,如果能输出最少需要的翻拍次数。
解法:bfs枚举每种情况。BYR论坛算法版给出的分类是枚举,但这题枚举要采取广搜策略。另外,注意到一共只有16个格,因此可以用一个16位的int存储状态,这样内存就不会超。存储每个状态是否被访问过可以直接用一个2^16个元素的flag数组完成。模拟翻牌过程用位运算即可。
代码:


Source Code
Problem: 1753 User: gp2593
Memory: 1120K Time: 32MS
Language: GCC Result: Accepted

* Source Code

#include<stdio.h>
#include<stdlib.h>
typedef struct node
{
int box;
int time;
int max;
}NODE;
turn(int bo,int positio)
{
int k,t;
t=1<<positio;
bo=bo^t;
if(positio+4<=15)
{
k=t<<4;
bo=bo^k;
}
if(positio-4>=0)
{
k=t>>4;
bo=bo^k;
}
if(positio%4!=0)
{
k=t>>1;
bo=bo^k;
}
if(positio%4!=3)
{
k=t<<1;
bo=bo^k;
}
return bo;
}
NODE a[70000];
main()
{
int i,t,position,mar,t1,c;
long k,j;

a[0].box=0;
a[0].time=0;
char bcd[10];
for(i=0;i<4;i++)
{
scanf("%s",bcd);
for(j=0;j<4;j++)
{
if(bcd[j]=='b')
{
position=1<<(j+i*4);
a[0].box=a[0].box+position;
}
}
}
mar=0;
if(a[0].box==0||a[0].box==65535)
mar=1;
if(mar==1)
{printf("0n");
}
else
{
k=0;j=1;mar=0;a[0].max=-1;
while(1)
{ t=a[k].box;
t1=a[k].time;
c=a[k].max;
for(i=c+1;i<16;i++)
{
a[j].box=turn(t,i);
a[j].time=t1+1;
a[j].max=i;
if(a[j].box==0||a[j].box==65535)
{mar=1;break;}
j++;
}
k++;
if(a[j-1].time==16)
break;
if(mar==1)
break;

}
if(mar==1){printf("%dn",a[j].time);}
else printf("Impossiblen");
}
}


Leave a Reply

Your email address will not be published. Required fields are marked *

CodePhoto.WTF © 2025