【数据结构•hash表】重排九宫…

来源:互联网 发布:数据透视表切片器 编辑:程序博客网 时间:2024/05/04 07:22

【数据结构•hash表】重排九宫

Time Limit:10000MS  MemoryLimit:65536K
Total Submit:47 Accepted:15

Description

我先来说几句:
====================================================================================================
  下面大家即将见到的是一道经典的广度搜索(bfs)题,bfs算法的运行耗时主要集中在状态扩展和状态判重上,大部分情况下,状态判重的耗时是远大于状态扩展的(假设可能扩展的状态数量为n,则其运算量分别为:o(n)和o(n^2)),如果在bfs算法中使用hash表去判重,则可以极大的提高运行效率。因此,bfs+hash,会是解决相当多搜索题的杀手锏!
  就下面例题而言,注意到每种状态构成了一个排列,我们可以给它分配一个编号,总共的状态数不会超过9!=362880种。(关于排列直接换算分配hash地址,可以见P1511理论基础知识,因此题状态数比较少,你可以使用简化的散列(hash)函数解决此题)。
====================================================================================================
  问题来了,重排九宫:
  将数字1~8按照人依次序排在3*3的方格阵列中,留下一个空位供数字方块移动,游戏的最终目标是通过合法移动将数字按行排好序。
输入举例:

【数据结构•hash表】重排九宫 <wbr>pascal <wbr>解题报告


目标:

【数据结构•hash表】重排九宫 <wbr>pascal <wbr>解题报告

输出达到目标状态的最少移动次数。

Input

  3*3的输入方阵,格式见样例。

Output

  一个整数,达到目标状态的最少移动次数。

SampleInput

1 2 3                         4 0 6                          7 5 8

SampleOutput

2

Hint

  本题测试数据贡献者:肖遥

Source

 

哈希表+广搜

哈希函数:先把二维转为一维,在用“康托展开式”,把一维转换成一个数。

康托展开式:一个排列在全排列中的位置。具体见http://baike.baidu.com/view/437641.htm

 

 

var
 head,tail:longint;
 a:array[0..10]of longint;
 f:array[0..362880,0..10]of longint;
 h:array[1..362880]of boolean;

procedure hash;
var
 i,j,s,e,k:longint;
begin
 s:=1;
 k:=1;
 for i:=9-1 downto 1 do
  begin
  e:=0;
  for j:=i+1 to 9 do
   if a[j]<a[i]then inc(e);
  s:=s+e*k;
  k:=k*(9-i+1);
  end;
  f[0,10]:=-1;
  if s=46234 then begin
  write(f[head,10]+1); halt; end;
  if h[s]=false then
  begin
  h[s]:=true;
  inc(tail);
  f[tail]:=a;
  f[tail,10]:=f[head,10]+1;
  end;
end;


procedure init;
var
 i,j:longint;
begin
 for i:=1 to 3 do
  for j:=1 to 3 do
   begin
   read(a[(i-1)*3+j]);
   if a[(i-1)*3+j]=0 thena[0]:=(i-1)*3+j;
   end;
 tail:=0;
 head:=0;
 hash;
end;

procedure change(i:longint);
begin
 a:=f[head];
 a[a[0]]:=a[a[0]+i];
 a[a[0]+i]:=0;
 a[0]:=a[0]+i;
 hash;
end;

procedure bfs;
var
 i:longint;
begin
 head:=1;
 tail:=1;
 f[1,10]:=0;
 while true do
  begin
   if f[head,0]mod 3=0 then
    begin
   change(-1);
    iff[head,0]<>9 then change(3);
    iff[head,0]<>3 then change(-3);
    end;
   if f[head,0]mod 3=2 then
    begin
   change(-1);
   change(1);
    iff[head,0]<>8 then change(3);
    iff[head,0]<>2 then change(-3);
    end;
   if f[head,0]mod 3=1 then
    begin
   change(1);
    iff[head,0]<>7 then change(3);
    iff[head,0]<>1 then change(-3);
    end;
   inc(head);
  end;
end;

begin
 fillchar(h,sizeof(h),0);
 init;
 bfs;
end.

0 0
原创粉丝点击