题3、八数码
问题描述
有3*3共9个格子,其中有一个格子是空的,其他格子填满了1-8之间不同的数字。通过移动格子可以改变数字和空格的位置,现在给你初状态和末状态,请你给出最少的步数。
问题输入
给出6行,每行有三个数,每两个数用一个空格空开,每个数在0~8之间,其中0表示空格。前三行表示初始状态,后三行表示目标状态。
问题输出
输出一行一个数,表示从初始状态移动到目标状态的最少步数。如果无解则输出-1。
分析:求最优解我们可以想到bfs,但是怎么记录状态判重是个问题。所以我们可以考虑把每种情况转成一个9位的十进制数然后hash就好了
代码
const
dx:array[1..4] of -1..1=(-1,0,1,0);
dy:array[1..4] of -1..1=(0,1,0,-1);
var
s:array[0..100000,1..3] of longint;
b:array[0..100000,0..4,0..4] of 0..9;
a:array[0..4,0..4] of 0..9;
ha:array[0..10000007] of int64;
i,j,k,x,y:longint;
ans:int64;
function check(x,y:longint):boolean;
begin
if (x<1) or (y<1) or (x>3) or (y>3) then exit(false);
exit(true);
end;
function hash(x:int64):longint;
var
tmp:longint;
begin
tmp:=x mod 10000007;
while (ha[tmp]<>0) and (ha[tmp]<>x) do
tmp:=(tmp+1) mod 10000007;
exit(tmp);
end;
procedure bfs;
var
h,t,i,j,k,p:longint;
o:int64;
begin
h:=0;
t:=1;
s[1,1]:=x;
s[1,2]:=y;
while h<t do
begin
inc(h);
for i:=1 to 4 do
begin
p:=0;
o:=0;
x:=s[h,1]+dx[i];
y:=s[h,2]+dy[i];
for k:=1 to 3 do
for j:=1 to 3 do
a[k,j]:=b[h,k,j];
a[s[h,1],s[h,2]]:=a[x,y];
a[x,y]:=0;
for j:=1 to 3 do
for k:=1 to 3 do
o:=o*10+a[j,k];
if check(x,y) and (ha[hash(o)]<>o) then
begin
inc(t);
s[t,3]:=s[h,3]+1;
s[t,1]:=x;
s[t,2]:=y;
ha[hash(o)]:=o;
for j:=1 to 3 do
for k:=1 to 3 do
b[t,j,k]:=a[j,k];
if o=ans then
begin
writeln(s[t,3]);
close(input);close(output);
halt;
end;
end;
end;
end;
end;
begin
//assign(input,'eight.in');reset(input);
//assign(output,'eight.out');rewrite(output);
for i:=1 to 3 do
for j:=1 to 3 do
begin
read(b[1,i,j]);
if b[1,i,j]=0 then
begin
x:=i;
y:=j;
end;
ans:=ans*10+b[1,i,j];
end;
ha[hash(ans)]:=ans;
ans:=0;
for i:=1 to 3 do
for j:=1 to 3 do
begin
read(k);
ans:=ans*10+k;
end;
bfs;
writeln(-1);
close(input);close(output);
end.