【搜索】【poj 1753】Flip Game

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

问题

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

分析

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

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

code

ContractedBlock.gif ExpandedBlockStart.gif 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 .

反思

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

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

转载于:https://www.cnblogs.com/liukeke/archive/2011/02/24/1963390.html

你可能感兴趣的:(【搜索】【poj 1753】Flip Game)