雙向BFS 八數碼問題

2021-06-27 23:25:49 字數 4583 閱讀 2359

【問題描述】

在3×3的棋盤上,擺有八個棋子,每個棋子上標有1至8的某一數字。棋盤中留有乙個空格,空格用0來表示。

空格周圍的棋子可以移到空格中。要求解的問題是:給出一種初始布局(初始狀態)和目標布局(目標狀態),

找到一種最少步驟的移動方法,實現從初始布局到目標布局的轉變。 

例如:2 8 3

1 6 4

7 0 5

初始狀態

1 2 3

8 0 4

7 6 5

目標狀態

最少步驟的移動方法是:

2 8 3

1 6 4

7 0 5

2 8 3

1 0 4

7 6 5

2 0 3

1 8 4

7 6 5

0 2 3

1 8 4

7 6 5

1 2 3

0 8 4

7 6 5

1 2 3

8 0 4

7 6 5

共5步達到目標狀態。

【輸入】

輸入檔案eight.in包含六行,每行三個數字,數字之間用空格間隔。前三行為初始狀態,後三行為目標狀態。

【輸出】

輸出檔案eight.out只有一行,該行只有乙個數字,表示從初始狀態到目標狀態需要的最少移動次數。

如果無法從初始狀態得到目標狀態,或移動步數超過20還不能得到目標狀態,則輸出「no solution!」。

input

2 8 3

1 6 4

7 0 5

1 2 3

8 0 4

7 6 5

output

5var i,j,t,w,q,e,tmp:longint;

g,y:array[1..100000,1..3,1..3]of longint;

time,wen:array[1..100000]of longint;

hash,p:array[0..362879]of boolean;

x,b:array[1..3,1..3]of longint;

z:array[1..9]of longint;

procedure wenjie;

var i,j:longint;

begin

for i:=1 to 3 do

for j:=1 to 3 do z[(i-1)*3+j]:=x[i,j];

end;

function rank:longint;

var i,j,t:longint;

begin

rank:=0;

for i:=2 to 9 do

begin

t:=0;

for j:=1 to i-1 do if z[i]>z[j] then inc(t);

for j:=2 to i-1 do t:=t*j;

rank:=rank+t;

end;

end;

function wwj:boolean;

var ans:longint;

begin

wenjie;

ans:=rank;

if hash[ans] then

begin

hash[ans]:=false;

exit(true);

endelse exit(false);

end;

function ty:boolean;

var ans:longint;

begin

wenjie;

ans:=rank;

if p[ans] then

begin

p[ans]:=false;

exit(true);

endelse exit(false);

end;

function zyq(f:longint):boolean;

var i,j:longint;

begin

for i:=1 to 3 do

for j:=1 to 3 do

if g[t,i,j]<>y[f,i,j] then exit(false);

exit(true);

end;

begin

fillchar(p,sizeof(p),true);

fillchar(hash,sizeof(hash),true);

for i:=1 to 3 do

for j:=1 to 3 do read(x[i,j]);

for i:=1 to 3 do

for j:=1 to 3 do read(b[i,j]);

t:=0;w:=1;q:=0;e:=1;

g[w]:=x;y[e]:=b;

time[w]:=0;wen[e]:=0;

wenjie;hash[rank]:=false;

x:=b;wenjie;p[rank]:=false;

while t20 then write('no solution!') else

write(time[t]+wen[i]);

halt;

end;

for i:=1 to 3 do

for j:=1 to 3 do

if g[t,i,j]=0 then

begin

if i-1>=1 then

begin

x:=g[t];tmp:=x[i,j];x[i,j]:=x[i-1,j];x[i-1,j]:=tmp;

if wwj then

begin

inc(w);

g[w]:=x;

time[w]:=time[t]+1;

end;

end;

if i+1<=3 then

begin

x:=g[t];tmp:=x[i,j];x[i,j]:=x[i+1,j];x[i+1,j]:=tmp;

if wwj then

begin

inc(w);

g[w]:=x;

time[w]:=time[t]+1;

end;

end;

if j-1>=1 then

begin

x:=g[t];tmp:=x[i,j];x[i,j]:=x[i,j-1];x[i,j-1]:=tmp;

if wwj then

begin

inc(w);

g[w]:=x;

time[w]:=time[t]+1;

end;

end;

if j+1<=3 then

begin

x:=g[t];tmp:=x[i,j];x[i,j]:=x[i,j+1];x[i,j+1]:=tmp;

if wwj then

begin

inc(w);

g[w]:=x;

time[w]:=time[t]+1;

end;

end;

end;

for i:=1 to 3 do

for j:=1 to 3 do

if y[q,i,j]=0 then

begin

if i-1>=1 then

begin

x:=y[q];tmp:=x[i,j];x[i,j]:=x[i-1,j];x[i-1,j]:=tmp;

if ty then

begin

inc(e);

y[e]:=x;

wen[e]:=wen[q]+1;

end;

end;

if i+1<=3 then

begin

x:=y[q];tmp:=x[i,j];x[i,j]:=x[i+1,j];x[i+1,j]:=tmp;

if ty then

begin

inc(e);

y[e]:=x;

wen[e]:=wen[q]+1;

end;

end;

if j-1>=1 then

begin

x:=y[q];tmp:=x[i,j];x[i,j]:=x[i,j-1];x[i,j-1]:=tmp;

if ty then

begin

inc(e);

y[e]:=x;

wen[e]:=wen[q]+1;

end;

end;

if j+1<=3 then

begin

x:=y[q];tmp:=x[i,j];x[i,j]:=x[i,j+1];x[i,j+1]:=tmp;

if ty then

begin

inc(e);

y[e]:=x;

wen[e]:=wen[q]+1;

end;

end;

end;

end;

end.

2 8 3

1 6 4

7 0 5

1 2 3

8 0 4

7 6 5

八數碼問題 雙向bfs

如 注釋的很清楚了 單向的還可以看看這個 以下是參考上面連線的雙向 include include include include include using namespace std int dr 2 queue int q1,q2 map int,int c1 記錄是否走過這個狀態,避免重複,...

HDU 1043 八數碼問題 雙向BFS

題目鏈結 題意 給你乙個初始狀態,問你能否移動到最終的完成狀態,如果能輸出任意一組解,否則輸出unsolved。思路 乍一看是個bfs,但是狀態過多會tle或者mle,但是除可bfs確實沒得寫了,這時候就要用到雙向bfs了,起點終點同時bfs,判斷相遇,路徑用string 就行了。注意點 正向路徑s...

BFS入門 八數碼問題

題目描述 初始狀態的步數就算1,哈哈 輸入 第乙個33的矩陣是原始狀態,第二個33的矩陣是目標狀態。輸出 移動所用最少的步數 input 2 8 3 1 6 4 7 0 5 1 2 3 8 0 4 7 6 5 output 思路 這道題bfs搜尋的每一步就是讓矩陣從乙個狀態變為另乙個狀態。所以我們用...