特长生模拟 八数码(bfs+hash)

8 篇文章 0 订阅

题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.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值