1.算法說明算法
[1]廣度優先搜索算法(BFS)主要用於計算源點到目標點的最短路徑。佈局
[2]BFS的基本實現是使用隊列,從源點開始入隊列,訪問後把臨近節點入隊列,以後出隊列,再訪問剛加進的臨近節點,以此反覆訪問,知道達到目標點。測試
2.算法步驟spa
1. 首先將根節點放入隊列中。3d
2. 從隊列中取出第一個節點,並檢驗它是否爲目標,若是找到目標,則結束搜尋並回傳結果,不然將它全部還沒有檢驗過的直接子節點加入隊列中。code
3. 若隊列爲空,表示整張圖都檢查過了,此時能夠返回結果,不然重複步驟2。blog
更具體地:隊列
以白色表示未達到的節點,灰色表示邊緣節點(意思是須要從這些節點繼續搜索),黑色表示已經達到的節點。字符串
1.在搜索的過程當中,初始全部節點是白色,把起點V0標誌成灰色。get
2.訪問全部灰色的節點的臨近節點,若是臨近節點是白色,則把這些臨近節點變爲灰色(此時判斷染灰色的節點是否爲目標節點,若是是則表示完成),不然表示已經到達過則不處理,並把當前節點變成黑色。
3.重複第2步。
3.例子
描述:
在3×3的棋盤上,擺有八個棋子,每一個棋子上標有1至8的某一數字。棋盤中留有一個空格,空格用0來表示。空格周圍的棋子能夠移到空格中。要求解的問題是:給出一種初始佈局(初始狀態)和目標佈局(爲了使題目簡單,設目標狀態爲123804765),
找到一種最少步驟的移動方法,實現從初始佈局到目標佈局的轉變。
輸入格式:
輸入初試狀態,一行九個數字,空格用0表示
輸出格式:
只有一行,該行只有一個數字,表示從初始狀態到目標狀態須要的最少移動次數(測試數據中無特殊沒法到達目標狀態數據)
代碼:
#include<cstdio> #include<cstring> #include<map> #include<stdlib.h> using namespace std; const int M=400000; /* 每一個0位置狀態時,能夠移動的位置 例如0在位置0時,能夠移動到1和3位置。 */ int g_change_position[9][4]={{-1,-1,3,1},{-1,0,4,2},{-1,1,5,-1}, {0,-1,6,4},{1,3,7,5},{2,4,8,-1}, {3,-1,-1,7},{4,6,-1,8},{5,7,-1,-1} }; int g_target = 123804765; /* g_map用來記錄狀態是否達到過,若是未達到過,則加入que隊列。 若是達到過則什麼都不處理。 例如初始把起點加入隊列,而且設置爲該狀態爲1,表示已達到過。 */ map<int,bool> g_map; /* 9!是362880,表示012345678這九個數字共有362880種排列組合 [][0] :排列值 [][1] :空位0的位置 [][2] :到此排列狀態所走的步數 que[400000]就是BFS的隊列,把將要搜索的節點放入隊列,以後再順序訪問隊列。 */ int que[400000][3]; // 交換字符串中的兩個位置 void swap(char *c,int a,int b){ char t=c[a]; c[a]=c[b]; c[b]=t; } /* head表示隊列que的起點,tail表示隊列que的終點,達到終點則退出。 初始時,把起點加入隊列,此時隊列長度爲1,所以起點爲0,終點爲1。 隊列中加入新節點時,隊列終點後移。 當前狀態搜索臨近節點後,把臨近節點加入隊列,隊列搜索位置後移。 */ int bfs(int n, int p) { int i, swap_pos; int head=0,tail=1,temp; //設置起點狀態達到,而且加入隊列 g_map[n]=1; que[head][0] = n; que[head][1] = p; que[head][2] = head; while(head != tail){ char cur[10]; int pos = que[head][1]; //當前狀態0的位置 sprintf(cur, "%09d", que[head][0]); //要交換的四個位置,上下左右 for(i=0;i<4;i++){ swap_pos = g_change_position[pos][i]; if(swap_pos == -1) continue; //交換0的位置,獲得新的狀態,轉爲int,保存到temp swap(cur, pos, swap_pos); sscanf(cur,"%d",&temp); if(temp == g_target) return que[head][2] + 1; //若是 新的狀態沒有出現過,則將這個新狀態加到map if(g_map.count(temp) == 0){ que[tail][0]=temp; que[tail][1]=swap_pos; que[tail][2]=que[head][2]+1; tail++; g_map[temp] = 1; } //一個新狀態處理完了必定要記得將交換的0交換回來 swap(cur, pos, swap_pos); } head++; } } int main() { int n, i = -1, count = 0; char start[10]; printf("input start array: "); scanf("%s", start); n = atoi(start); while(start[++i] != '0'); //查找初始狀態0的位置 if(n != g_target) count = bfs(n, i); printf("%d", count); return 0; }
[1]BFS搜索時,最基本是用了隊列que來保存已到達的狀態,以後順序訪問隊列,把新狀態再加到隊列中。