A*算法在8數碼(滑塊拼圖)問題中的應用理解

關於A*算法,有些資料講解很不錯,如

https://blog.csdn.net/hitwhylz/article/details/23089415

https://www.jianshu.com/p/a3951ce7574d

在上篇滑塊拼圖的問題

https://blog.csdn.net/aaajj/article/details/100375751

處理後,我發現,從廣度優先搜索(BFS)的角度去理解A*算法非常清晰易懂。

A*可以看成是對廣度優先搜索的一種改進,在BFS中,使用隊列保存每層中的節點,

從隊列頭部取出節點進行檢查的時候,再將其子節點都放到隊列的尾部,這樣實現按照層次查找的效果。

 

A*對節點隊列進行了處理,總是優先對估值低(最優)的節點進行處理,這有些類似動態規劃,這樣就避免了BFS搜索的盲目性。

體現出了“以正合,以奇勝”的哲學思想

 

使用一個表(隊列)來存放待檢查的節點

 

 

 

 

Open表可以使用一個有序鏈表結構來實現,主要有添加和刪除操作,如

 

//test A*

void addNode(PNode* head, PNode* data)

{

    while (head->next != NULL)

    {

        PNode* t = head->next;

        //already in the list

        if (t == data)

        {

            return;

        }

 

        if (data->f < t->f)

        {

            data->next = t;

            head->next = data;

            return;

        }

        head = head->next;

    }

 

    if (head->next == NULL)

    {

        head->next = data;

        data->next = NULL;

    }

}

 

void rmNode(PNode* head, PNode* data)

{

    while (head->next != NULL)

    {

        PNode* t = head->next;

        if (t == data)

        {

            head->next = t->next;

            delete t;

            return;

        }

        head = head->next;

    }

}

 

Close表由於需要經常用來查找,可以使用map來實現

 

估值函數h一般要在一定程度上表現出各節點間距離的差異。

對於8數碼以及滑塊拼圖問題,估值函數h可以簡單的用不匹配的滑塊數量來表示,如

目標:

1 2 3

4 5 6

7 8 0

 

狀態A

1 2 3

4 0 5

7 8 6

的h值爲3,有3個位置不匹配,A可以通過滑動0到達狀態B和C

B:(h值爲2)

1 2 3

4 5 0

7 8 6

 

C:(h值爲4)

1 2 3

0 4 5

7 8 6

顯然,從狀態A進行移動選擇的時候,選擇h值爲2的B狀態更好,事實也確實如此。

 

h函數也可以稍微複雜點的絕對距離和來表示

以狀態A爲例

1 2 3

4 0 5

7 8 6

計算每個滑塊分別單獨放好的步數,對其求和來作爲h估值

這裏,h=h(1) +h(2)+h(3)+h(4)+h(5)+h(6)+h(7)+h(8)+h(0)

=0   + 0  +0   + 0 + 1+  1   + 0   + 0+ 2

=4

我們也可以不把空白塊0計算進去,這要看對h函數的具體設計。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章