黑白棋游戏
源程序名 game.???(pas, c, cpp) 可执行文件名 game.exe 输入文件名 game.in 输出文件名 game.out |
【问题描述】
黑白棋游戏的棋盘由4×4方格阵列构成。棋盘的每一方格中放有1枚棋子,共有8枚白棋子和8枚黑棋子。这16枚棋子的每一种放置方案都构成一个游戏状态。在棋盘上拥有1条公共边的2个方格称为相邻方格。一个方格最多可有4个相邻方格。在玩黑白棋游戏时,每一步可将任何2个相邻方格中棋子互换位置。对于给定的初始游戏状态和目标游戏状态,编程计算从初始游戏状态变化到目标游戏状态的最短着棋序列。
【输入】
输入文件共有8行。前四行是初始游戏状态,后四行是目标游戏状态。每行4个数分别表示该行放置的棋子颜色。“0”表示白棋;“1”表示黑棋。
【输出】
输出文件的第一行是着棋步数n。接下来n行,每行4个数分别表示该步交换棋子的两个相邻方格的位置。例如,abcd表示将棋盘上(a,b)处的棋子与(c,d)处的棋子换位。
【样例】
game.in game.out
1111 4
0000 1222
1110 1424
0010 3242
1010 4344
0101
1010
0101
================
宽搜
状态的存储,
和八数码一样,这道题难在状态的存储
本题可以将状态转化为2进制...可将空间优化到1..2^16.
---------------
位操作的实现...
================
type
arr=array[1..4,1..4]of longint;
var
map,map1:array[1..4,1..4]of longint;
f:array[1..65536]of boolean;
aim,start:longint;
h:array[1..200000,1..3]of longint;
procedure init;
begin
assign(input,'game.in');
assign(output,'game.out');
reset(input); rewrite(output);
end;
procedure terminate;
begin
close(input); close(output);
halt;
end;
function gethash(a:arr):longint;
var
i,j:longint;
begin
gethash:=0;
for i:=1 to 4 do
for j:=1 to 4 do
gethash:=(gethash)shl 1+a[i,j];
end;
function get(t:longint):arr;
var
i,j:longint;
//l,x,y:longint;
begin
for i:=1 to 4 do
for j:=1 to 4 do
begin
get[i,j]:=(t shr (16-(i-1)*4-j))and 1;
end;
end;
procedure change(x,y,x_,y_:longint;var b:arr);
var
tem:longint;
begin
tem:=b[x,y];
b[x,y]:=b[x_,y_];
b[x_,y_]:=tem;
end;
procedure print(t,n:longint);
begin
if h[t,2]<>0 then print(h[t,2],n+1);
if h[t,2]=0 then begin writeln(n); exit; end;
writeln(h[t,3]);
end;
procedure bfs;
var
l,r,i,j,hash_:longint;
a,b:arr;
begin
l:=0; r:=1;
h[1,1]:=start;
h[1,2]:=0;
h[1,3]:=0;
repeat
inc(l);
a:=get(h[l,1]);
for i:=1 to 4 do
for j:=1 to 3 do
begin
b:=a;
change(i,j,i,j+1,b);
hash_:=gethash(b);
if f[hash_] then
begin
f[hash_]:=false;
inc(r);
h[r,1]:=hash_;
h[r,2]:=l;
h[r,3]:=i*1000+j*100+i*10+(j+1);
if aim=hash_ then
begin
print(r,0);
terminate;
end;
end;
end;
for i:=1 to 3 do
for j:=1 to 4 do
begin
b:=a;
change(i,j,i+1,j,b);
hash_:=gethash(b);
if f[hash_] then
begin
f[hash_]:=false;
inc(r);
h[r,1]:=hash_;
h[r,2]:=l;
h[r,3]:=i*1000+j*100+(i+1)*10+j;
if aim=hash_ then
begin
print(r,0);
terminate;
end;
end;
end;
until l>=r;
end;
procedure main;
var
ch:char;
i,j:longint;
begin
fillchar(f,sizeof(f),true);
for i:=1 to 4 do
begin
for j:=1 to 4 do
begin
read(ch);
map[i,j]:=ord(ch)-ord('0');
end;
readln;
end;
start:=gethash(map);
f[start]:=false;
for i:=1 to 4 do
begin
for j:=1 to 4 do
begin
read(ch);
map1[i,j]:=ord(ch)-ord('0');
end;
readln;
end;
aim:=gethash(map1);
bfs;
end;
begin
init;
main;
terminate;
end.