这题也算是经典题了,好早之前就看到了,一直没啥想法做,知道是状态压缩,可是没细想过。
A过上道题,就想找个状态压缩的试试哈,就找到这个题啦。
很容易想到,4*4的格子,用一个16位的存下(用int绰绰有余~)就好,这样的话,一个状态就可以用一个数字表示了,标记状态是否用过,用65535的数组就够了。
这个^=好神奇,我开始用了俩位运算表示这个,囧。。。A掉之后觉得时间好慢,看别人的,才看到这个符号。。囧。。
位运算好神奇。。。我开始用的四个方向,先把位置换算成4*4中得坐标,再找上下左右四个方向,慢了几十ms。。。别人用的直接+4 -4 +1 -1(后俩得判断是否越当前行的界),这个很快~
int st_change(int st, int x)
{
st ^= (1 << x);
int a = x/4, b = x % 4;
for(int i=0; i<8; i+=2)
{
int xx = a + dir[i];
int yy = b + dir[i+1];
if( xx >= 0 && xx < 4 && yy >= 0 && yy < 4 )
{
int p = ( xx * 4 + yy );
st ^= (1 << p);
}
}
return st;
}
int st_change(int st, int x)
{
st ^= (1 << x);
if( x + 4 < 16 )
st ^= (1 << (x + 4));
if( x - 4 >= 0 )
st ^= (1 << (x - 4));
if( x % 4 < 3 && x + 1 < 16 )
st ^= (1 << (x + 1));
if( x % 4 > 0 && x - 1 >= 0 )
st ^= (1 << (x - 1));
return st;
}
完整版:
#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <iostream>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define FOR(i,s,t) for(int i=(s); i<(t); i++)
#define BUG puts("here!!!")
#define STOP system("pause")
#define file_r(x) freopen(x, "r", stdin)
#define file_w(x) freopen(x, "w", stdout)
using namespace std;
const int MAX = 70000;
bool used[MAX];
typedef pair<int,int> pii;
queue<pii> q;
int st_change(int st, int x)
{
st ^= (1 << x);
if( x + 4 < 16 )
st ^= (1 << (x + 4));
if( x - 4 >= 0 )
st ^= (1 << (x - 4));
if( x % 4 < 3 && x + 1 < 16 )
st ^= (1 << (x + 1));
if( x % 4 > 0 && x - 1 >= 0 )
st ^= (1 << (x - 1));
return st;
}
int solve(int st)
{
while( !q.empty() ) q.pop();
if( st == 0 || st == 65535 )
return 0;
q.push(make_pair(st, 0));
while( !q.empty() )
{
st = q.front().first;
int t = q.front().second;
q.pop();
FOR(i, 0, 16)
{
int now = st_change(st, i);
if( now == 0 || now == 65535 )
return t + 1;
if( !used[now] )
{
used[now] = true;
q.push(make_pair(now, t+1));
}
}
}
return -1;
}
int main()
{
int ncases, st;
char s[10];
scanf("%d", &ncases);
while( ncases-- )
{
st = 0;
memset(used, false, sizeof(used));
FOR(i, 0, 4)
{
scanf("%s", &s);
FOR(k, 0, 4)
if( s[k] == 'b' )
st = st | ( 1 << (i * 4 + k) );
}
used[st] = true;
int ans = solve( st );
if( ans == -1 )
puts("Impossible");
else
printf("%d\n", ans);
if( ncases ) puts("");
}
return 0;
}