【問題描述】
在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搜尋的每一步就是讓矩陣從乙個狀態變為另乙個狀態。所以我們用...