【資料結構•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的方格陣列中,留下一個空位供數字方塊移動,遊戲的最終目標是通過合法移動將數字按行排好序。
輸入舉例:
目標:
輸出達到目標狀態的最少移動次數。
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.