【搜索】【poj 1753】Flip Game

不错的搜索题,原题目如下:http://poj.org/problem?id=1753

问题

就是翻转棋,反当前这个会引起其周围棋子的变化,就是取反的过程。问你经过一个最小反转次数能否得到全都是黑棋,或全是白棋的情况,如果不能,输出impossible。

分析

一看就知道是搜索,每个棋两种状态,那么共有2^16=65536种状态,所以想到了位运算。用每个二进制位代表棋子,定义坐标和第i个棋子的转换方法(代码中有,不再多说)。利用xor运算进行变换(xor 0则不变,xor 1 则取反)。

开一个哈希表判重,即可。

code

View Code
program liukee;
type lkj=record
lz:longint;
cc:longint;
end;

var
d:
array[1..4,1..2] of integer=((1,0),(-1,0),(0,1),(0,-1));
hash:
array[0..65537] of boolean;
q:
array[0..1000000] of lkj;
st:longint;

procedure init;
var
i,j:longint;
ch:char;
begin
for i:=1 to 4 do
begin
for j:=1 to 4 do
begin
read(ch);
if ch='b' then
st:
=st xor (1<< ((i-1)*4+j-1) );
end;
readln;
end;
end;

procedure bfs;
var
l,r,i,j:longint;
now,now1,x,y,xx,yy:longint;
begin
l:
=0;
r:
=1;
q[r].lz:
=st;
q[r].cc:
=0;
hash[st]:
=true;
while l<r do
begin
inc(l);
now:
=q[l].lz;
for i:=1 to 16 do
begin
x:
=(i div 4)+1;
if i mod 4=0 then dec(x);
y:
=i mod 4;
if y=0 then y:=4;
now1:
=now xor (1<<(i-1));
for j:=1 to 4 do
begin
xx:
=x+d[j,1];
yy:
=y+d[j,2];
if(xx>0)and(xx<5)and(yy>0)and(yy<5)then
now1:
=now1 xor (1<<((xx-1)*4+yy-1));
end;
if hash[now1] then continue;
if (now1=0) or (now1=65535) then
begin
writeln(q[l].cc
+1);
halt;
end
else
begin
inc(r);
q[r].lz:
=now1;
q[r].cc:
=q[l].cc+1;
hash[now1]:
=true;
end;
end;
end;
end;

procedure outit;
begin
writeln(
'Impossible');
end;

begin
st:
=0;
fillchar(hash,sizeof(hash),
0);
assign(input,
'try.in');reset(input);
assign(output,
'try.out');rewrite(output);
init;
if(st=0)or(st=65535) then
begin
writeln(
0);
halt;
end;
bfs;
outit;
end.

反思

定义转换法则要细心,每行最后一个棋子要特殊考虑。

在利用哈希表时,一定要等到产生一个完整的状态之后,不能在中途跳出,这样会删去好多状态。

posted @ 2011-02-24 08:28  liukee  阅读(265)  评论(0编辑  收藏  举报