【搜索】【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.
反思
定义转换法则要细心,每行最后一个棋子要特殊考虑。
在利用哈希表时,一定要等到产生一个完整的状态之后,不能在中途跳出,这样会删去好多状态。