Ural_1060. Flip Game(bfs + 位压缩)

  /*不明白为什么Ural把这题归到game里边,难到是因为这题是个游戏。。。很水的一
道题,纠结了两天,以前没有接触过位压缩,估计学过位压缩的童鞋能够把这题直接秒
掉,Orz各位做题神速的童鞋。。。

  wwww
  wwww
  wwwb
  wwbb

可以用二进制表示为:1100|1000|0000|0000;

也就是说4*4方格里所有状态都可以用16位二进制表示,转成十进制后为0或者65535就完
成了游戏。
*/

//My Code:

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int N = 65536;
struct node{
int s; //当前状态;
int t; //改变的次数;
}q[N];

bool vis[N];

int change(int p, int i){
p ^= (1 << i); //当前位置改变
if(i+4 < 16) p ^= (1 << (i + 4)); //
if(i-4 >= 0) p ^= (1 << (i - 4)); //
if(i%4 < 3 && i+1 < 16) p ^= (1 << (i + 1)); //
if(i%4 > 0 && i - 1 >= 0) p ^= (1 << (i - 1)); //
return p;
}

int bfs(int p){
if(p == 0 || p == 65535) return 0; //游戏结束条件
int f = 0, r = 0, t = 0, i, pn;
q[r].s = p; q[r].t = t; r++; //初始状态入队列

while(f < r){ //暴搜
p = q[f].s; t = q[f].t; f++;
for(i = 0; i < 16; i++){
pn = change(p, i);
if(pn == 0 || pn == 65535) return t+1;
if(!vis[pn]){
vis[pn] = true; //每种状态保证只出现一次,否则。。。能搜死
q[r].s = pn; q[r].t = t+1; r++;
}
}
}
return -1;
}
int main(){
//freopen("data.in", "r", stdin);

int ans, i, j, p = 0;
memset(vis, false, sizeof(vis));
char map[5][5];
for(i = 0; i < 4; i++){
scanf("%s", map[i]);
for(j = 0; j < 4; j++){
if(map[i][j] == 'b')
p = p | (1 << (i*4 + j));
}
}
vis[p] = true;
ans = bfs(p);
if(ans == -1) printf("Impossible\n");
else printf("%d\n", ans);
return 0;
}

你可能感兴趣的:(game)