接上一篇本题dfs
耗时2天写出来的第一个位运算。
唯一记住一件事:网上推荐poj刷题水题请千万不要相信它水。
传送poj 1753
因为每个棋子只有黑白2种颜色可以用0,1两个数字来表示,这样用16个0或者1,就可以表示出来当前期盼的状态。然后使用异或操作将需要翻的棋子翻过来。
推荐一篇博客哦,讲的很详细,而且写的不太一样
戳
直接上代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
bool vis[65535]={0};
int step[65535];
int k;
int x;//存储棋盘当前状态
queue<int> q;
int flip(int x,int pos)//当前棋盘为x状态时,翻第i个棋子 ,感谢题解大大和Sirius同学 w
{
x=x^(1<<pos); //翻pos上的棋子
if(pos%4!=0) x=x^(1<<(pos-1));//左
if(pos>=4) x=x^(1<<(pos-4)); //上
if(pos%4!=3) x=x^(1<<(pos+1)); //右
if(pos<12) x=x^(1<<(pos+4));//下
return x;
}
int bfs(int x)
{
memset(vis,0,sizeof(vis)); //visit数组记录有无被翻
step[x]=0;
q.push(x);
vis[x]=1;
while(!q.empty())
{
int now=q.front();
q.pop();
for(int i = 0; i < 16; i++) //遍历每一个点
{
int next=flip(now,i);//翻转当前情况
if(vis[next]!=0) //这个点被翻过了,翻下一个点
{
continue;
}
step[next]=step[now]+1;
if(next == 0 || next == 65535) //达到目标状态
{
return step[next];
}
vis[next]=1; //这个点被翻过啦
q.push(next); //当前状态载入队列
}
}
return -999; //搜完所有也达不到
}
int main()
{
char chess[10];
x=0;
for(int i=0;i<4;i++) //输入陷害朕啊!!!一开始就输错了,找了个题解对照一下输入。。汗
{
scanf("%s",chess); //输入4行
//printf("%s",chess);
for(int j=0;j<4;j++,k++)
{
if(chess[j] == 'b')
{
x+=1<<k;
}
else
{
x+=0<<k;
}
}
}
//printf("%d\n",x);
if( x == 0|| x == 65535)
{
cout<<'0'<<endl;
}
else
{
int ans=bfs(x);
if(ans == -999)
{
cout<<"Impossible"<<endl;
}
else
{
cout<<ans<<endl;
}
}
}
朕心情愉悦【笑
然后周一月考呵呵呵。
再然后 a better tomorrow
nighty