八数码
1 问题描述
有 3 × 3 共 9 个格子,其中有一个格子是空的,其他格子填满了 1 ∼ 8 之间不同的数字。通过
移动格子可以改变数字和空格的位置,现在给你初状态和末状态,请你给出最少的移动步数。
2 输入格式
输入文件名为 eight.in 。
给出 6 行,每行有 3 个数,每两个数用一个空格空开,每个数在 0 ∼ 8 之间,其中 0 表示空
格。
前 3 行表示初始状态,后 3 行表示目标状态。
3 输出格式
输出文件名为 eight.out 。
输出一行一个数,表示从初始状态移动到目标状态的最少步数。
1 问题描述
有 3 × 3 共 9 个格子,其中有一个格子是空的,其他格子填满了 1 ∼ 8 之间不同的数字。通过
移动格子可以改变数字和空格的位置,现在给你初状态和末状态,请你给出最少的移动步数。
2 输入格式
输入文件名为 eight.in 。
给出 6 行,每行有 3 个数,每两个数用一个空格空开,每个数在 0 ∼ 8 之间,其中 0 表示空
格。
前 3 行表示初始状态,后 3 行表示目标状态。
3 输出格式
输出文件名为 eight.out 。
输出一行一个数,表示从初始状态移动到目标状态的最少步数。
如果无解则输出 -1。
-------------------------------------------------------------------------------------------分割线----------------------------------------------------------------------------------------------------
const
model=1000007;
type
arr=array[1..3,1..3] of longint;
var
cons:array[1..9] of longint;
head1,tail1,head2,tail2,p,i,j,min,x,y,stp:longint;
a,b,c:array[1..3,1..3] of longint;
rec,que1,que2:array[0..model] of int64;
t,step1,step2:array[0..model] of longint;
procedure p1;
begin
assign(input,'eight.in');
assign(output,'eight.out');
reset(input);
rewrite(output);
end;
procedure p2;
begin
close(input);
close(output);
end;
function work(a:arr):int64;
var
i,j:longint;sum:int64;
begin
sum:=0;
for i:=1 to 3 do
for j:=1 to 3 do sum:=sum*10+a[i,j];
exit(sum);
end;
function hash(x:int64):longint;
var
num:int64;
begin
num:=sqr(x mod model) mod model;
while (rec[num]<>0) and (rec[num]<>x) do num:=(num+1) mod model;
if rec[num]=0 then rec[num]:=x;
exit(num);
end;
procedure change(x1,y1,x2,y2:longint);
var tmp:longint;
begin
tmp:=c[x1,y1];c[x1,y1]:=c[x2,y2];c[x2,y2]:=tmp;
end;
procedure ins1(xx,yy:longint);
begin
inc(tail1);step1[tail1]:=stp+1;change(xx,yy,x,y);que1[tail1]:=work(c);t[hash(work(c))]:=stp+1;change(xx,yy,x,y);
end;
procedure ins2(xx,yy:longint);
begin
inc(tail2);step2[tail2]:=stp+1;change(xx,yy,x,y);que2[tail2]:=work(c);t[hash(work(c))]:=-stp-1;change(xx,yy,x,y);
end;
procedure init(num:int64);
var
i,j:longint;
begin
for i:=1 to 3 do
for j:=1 to 3 do begin
c[i,j]:=num div cons[i*3+j-3] mod 10;
if c[i,j]=0 then begin x:=i;y:=j;end;
end;
end;
function check(xx,yy:longint):boolean;
var tt:boolean;
begin
tt:=(min=maxlongint)and (1<=xx) and (xx<=3) and (1<=yy) and (yy<=3);
if tt then begin
change(xx,yy,x,y);
tt:=(t[hash(work(c))]=maxlongint);
if not tt and (t[hash(work(c))]*p<0) then min:=abs(t[hash(work(c))])+stp+1;
change(xx,yy,x,y);
end;
exit(tt);
end;
begin
p1;
cons[9]:=1;for i:=8 downto 1 do cons[i]:=cons[i+1]*10;
for i:=0 to 1000007 do t[i]:=maxlongint;
fillchar(rec,sizeof(rec),0);
for i:=1 to 3 do
for j:=1 to 3 do read(a[i,j]);
for i:=1 to 3 do
for j:=1 to 3 do read(b[i,j]);
head1:=1;tail1:=1;que1[1]:=work(a);step1[1]:=0;t[hash(que1[1])]:=0;
head1:=1;tail2:=1;que2[1]:=work(b);step2[1]:=0;t[hash(que2[1])]:=0;
if que1[1]=que2[1] then begin
writeln('0');
exit;
end;
min:=maxlongint;
while (head1<=tail1) and (head2<=tail2) and (min=maxlongint) do begin
init(que1[head1]);stp:=step1[head1];p:=1;
if check(x-1,y) then ins1(x-1,y);
if check(x+1,y) then ins1(x+1,y);
if check(x,y+1) then ins1(x,y+1);
if check(x,y-1) then ins1(x,y-1);
inc(head1);
init(que2[head2]);stp:=step2[head2];p:=-1;
if check(x-1,y) then ins2(x-1,y);
if check(x+1,y) then ins2(x+1,y);
if check(x,y+1) then ins2(x,y+1);
if check(x,y-1) then ins2(x,y-1);
inc(head2);
end;
if min=maxlongint then writeln('-1') else writeln(min);
p2;
end.