八数码问题(hash+折半搜索)

八数码
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.


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值