廣度優先搜索

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來保存已到達的狀態,以後順序訪問隊列,把新狀態再加到隊列中。

相關文章
相關標籤/搜索