1. 用雙向bfs解決八數碼問題
2. 用迭代加深搜的a*演算法解決八數碼問題
注:本實驗我採用的都是從283104765到123804765的最短步數
首先,雙向bfs指的是從初始狀態和目標狀態同時開始搜尋,廣度優先搜尋是每次先搜尋周圍,然後再向外擴充套件,(這裡我們把矩陣轉化為數字序列,更方便)我將用乙個佇列先把初始序列和目標序列依次放入佇列q,分別為第乙個和第二個,然後根據bfs的先進先出的特性,將會按順序一層一層的搜尋,當從初始序列開始後,會移動空格(這裡用0表示)並交換位置,然後把交換位置,之後的序列依次入隊,初始狀態序列bfs完後,就輪到第二個目標狀態序列了,同樣會產生交換位置之後的序列,這樣的話就可以實現從初始狀態和目標狀態兩頭同時進行bfs搜尋,會大大加快速度,終止條件就是當兩頭出現相交時,為結束。
//雙向bfs,從起點和終點兩個方向開始搜尋,
//如果某乙個狀態下出現相交的情況,那麼就出現了答案
#include
#include
#define ll long long int
using
namespace std;
//這裡我們把矩陣轉化為數字序列,更方便
int start, target =
123804765
;//start表示開始序列,target表示目標序列
int a[4]
[4], fx, fy, nx, ny;
int dx[4]
=;//代表四個移動方向
int dy[4]
=;queue<
int> q;
map<
int,
int> ans;
//ans用來記錄步數
map<
int,
int> v;
//v用來記錄狀態,是否順序和逆序訪問過
void
solve()
q.push
(start)
;//起始狀態和終止狀態依次入隊
q.push
(target)
; ans[start]=0
;//ans記錄步數
ans[target]=1
; v[start]=1
;//狀態1表示順序訪問過,即從起點開始搜尋
v[target]=2
;//狀態2表示逆序訪問過,即從終點開始搜尋
while
(!q.
empty()
)}}for
(int i =
0; i <
4; i++)}
if(v[now]
== v[cur])if
(v[now]
+ v[cur]==3
) ans[now]
= ans[cur]+1
; v[now]
= v[cur]
;//與上一狀態的方向保持一致
q.push
(now)
;//把的移動後的序列入隊
swap
(a[fx]
[fy]
, a[nx]
[ny]);
// 移動完了之後還要還原}}
}int
main()
結果:
由於迭代加深搜的a演算法裡面其實包含了深度優先搜尋,所以我就不再另外寫dfs演算法了,其實ida演算法就是廣度優先搜尋和深度優先搜尋和a*演算法三者的結合,可以通過自己設定,最大深度maxdep,逐步加大搜尋深度來獲得最優解,而如果使用dfs搜尋策略的話,就需要對整個搜尋空間進行搜尋,採用估值函式,剪掉f(n)>maxdep的路徑,通過剪枝去掉重複的路徑,可以大大減小時間複雜度。
#include
using
namespace std;
int dis[9]
[9]=
,//即從該點到其它8個點需要移動的步數,,
,,,,
,};int yuan[9]
=;//每個數字的目標狀態的位置
int chu[3]
[3];
//儲存當前狀態
char k;
int sx, sy;
int ax[4]
=;int ay[4]
=;//這兩個陣列一定要對稱寫,使搜尋時不會返回上一狀態
bool flag;
inth()
return ans;
}void
dfs(
int ceng,
int dep,
int f,
int x,
int y)
for(
int i =
0; i <
4; i++)}
intmain()
}}if(
!h()
) flag =0;
int maxdep;
//預期深度
for(maxdep =1;
; maxdep++)}
return0;
}
結果:
HDOJ 1043 八數碼問題(A 解法)
簡介 乙個九宮格中有八個數字,一位空格,每次只能移動相鄰的兩個格仔,現要求把九宮格變為 12345678x 的樣子 x代表空格 sample input 2 3 4 1 5 x 7 6 8 sample output ullddrurdllurdruldr 這裡我們要用到康拓展開,具體介紹如下 康拓...
八數碼問題
八數碼問題 一.八數碼問題 八數碼問題也稱為九宮問題。在3 3的棋盤,擺有八個棋子,每個棋子上標有1至8的某一數字,不同棋子上標的數字不相同。棋盤上還有乙個空格,與空格相鄰的棋子可以移到空格中。要求解決的問題是 給出乙個初始狀態和乙個目標狀態,找出一種從初始轉變成目標狀態的移動棋子步數最少的移動步驟...
八數碼問題
2 6 4 1 3 7 0 5 8 8 1 5 7 3 6 4 0 2 樣例輸出 還有就是重判的問題,如何重判呢?第一種方法 把排列變成整數,然後只開乙個一維陣列,也就是說設計一套排列的編碼和解碼函式,把0 8的全排列和0 362879的整數意義一一對應起來。時間效率高,但編碼解碼法適用範圍並不大,...