1. 程式人生 > >【資料結構•hash表】重排九宮…

【資料結構•hash表】重排九宮…

【資料結構•hash表】重排九宮

Time Limit:10000MS  Memory Limit: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

  一個整數,達到目標狀態的最少移動次數。

Sample Input

Sample Output

Hint

  本題測試資料貢獻者:肖遙

Source

雜湊表+廣搜

雜湊函式:先把二維轉為一維,在用“康託展開式”,把一維轉換成一個數。

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 then a[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);
    if f[head,0]<>9 then change(3);
    if f[head,0]<>3 then change(-3);
    end;
   if f[head,0]mod 3=2 then
    begin
    change(-1);
    change(1);
    if f[head,0]<>8 then change(3);
    if f[head,0]<>2 then change(-3);
    end;
   if f[head,0]mod 3=1 then
    begin
    change(1);
    if f[head,0]<>7 then change(3);
    if f[head,0]<>1 then change(-3);
    end;
   inc(head);
  end;
end;

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