A*尋路演算法(曼哈頓距離)

來源:互聯網
上載者:User

標籤:a演算法   a星演算法   尋路演算法   js   javascript   

前一些天,在群有人問到A*演算法的問題。之前我已經有實現過,並將之放到github上(https://github.com/XJM2013/A_Star);有興趣的可以下載下來看看。

這裡上傳了一個相當好的A*演算法示範程式,大家可以下載下來看看效果:http://download.csdn.net/detail/a374826954/8781185。

下面描述是摘自清華大學出版社《人工智慧》一書:

評價函數的形式如下:

f(n) = g(n) + h(n)

其中,n是被評價的結點。

g*(n):表示從初始結點s到結點n的最短的耗散值;

h*(n):表示從結點n到目標結點g的最短的耗散值;

f*(n)=g*(n)+h*(n):表示從結點s經過結點n到目標結點g的最短路徑的耗散值。

而f(n)、g(n)和h(n)則分別表示是對f*(n)、g*(n)和h*(n)3個函數值的估計值,的一種預測。A演算法就是利用這種預測,來達到搜尋的目的。

當在演算法A的評價函數中,使用的啟發函數h(n)是處於h*(n)的下界範圍,即滿足h(n)≤h*(n)時,則把這個演算法稱為演算法A*。

需要說明的是,程式由於增加了一些調試資訊,稍微會比實際慢一些。

下面看一下程式示範介面:


白格子表示通路,黑格子表示阻擋。

這裡的黑格子是隨機產生,在收下代碼產生:

(function(){map.init(0.3);map.createUI();})();

隨機數為0.3,當設定為0時,則全部都是通路。

說說3個按鈕:

“設定阻擋”:按下這個按鈕後可以通過滑鼠左鍵自訂阻擋地區,方便測試。

“closed”:顯示已經被擴充並放到closed表的節點資訊。顯示資訊以C:開頭;顯示4個資料分別是f,g,h和擴充索引;需要注意的是擴充索引不一定是連續的,因為同一個節點可能被多次擴充。

“open”:顯示剩餘剩餘的open表節點資訊。顯示資訊以O:開頭;顯示3個資料分別是f,g和h。


其實一些人搞不懂A*演算法,主要是搞不懂f,g,h是怎樣取值的。

下面舉個例子:

從廣州到北京(最好開啟百度地圖對比著看,以下距離不等於實際城市間的距離)

換言之,廣州就是起始點,北京就是目標點。

廣州到廣州的距離是0,也就是g=0;廣州到北京的直線距離是5000,也就是h=5000。f=g+h,f=5000。

將廣州放進open表,擴充廣州這個節點,並將廣州從open表刪除,放進closed表;得到重慶和上海。


廣州到重慶的距離是2500,也就是重慶這個節點的g=2500;重慶到北京的直線距離是4500,也就是h=4500;f=7000。

將重慶放進open表。

廣州到上海的距離是3000,也就是上海這個節點的g=3000;上海到北京的直線距離是3000,也就是h=3000;f=6000。

將上海放進open表;由於上海的f小於重慶的f,在open表中上海節點在重慶節點前面。


擴充上海這個節點,發現找到了北京,於是搜尋結束。最後的路徑就是廣州-上海-北京。

本程式的核心代碼是:

search : function(){    while(1){    if (map.openTable.length == 0){    break;    }            var _fMinNode = map.openTable.shift();            if (_fMinNode.place == 2){            continue;            }                        map.searchAround(_fMinNode);            _fMinNode.index = globalIndex;            globalIndex++;            _fMinNode.place = 2;closedTable.push(_fMinNode);            if (map.endNode == _fMinNode){            break;            }        }    },        searchAround : function(node){        var nodeX;        var nodeY;        for (var x = -1; x <= 1; x++)         {            nodeX = node.x + x;            for (var y = -1, mapNode, _obj, tmpNode; y <= 1; y++)             {                nodeY = node.y + y;                //剔除本身                if (x === 0 && y === 0) continue;                if (nodeX >= 0 && nodeY >= 0 && nodeX < map.gridWidth && nodeY < map.gridHeight)                 {                    mapNode = map.data[nodeX][nodeY];                    if (mapNode.isRoadBlock){                    continue;                    }_obj = map.getFGH(node, mapNode);do{if (mapNode.place == 2){if (_obj.G >= mapNode.obj.G){break;}}else if (mapNode.place == 1){// 單調限制if (mapNode.obj.G <= _obj.G){continue;}}                                                mapNode.obj = _obj;                        mapNode.front = node;                        mapNode.place = 1;                        map.insertOpenTable(mapNode);}while(0)                };            };        };    },

工作流程就是迴圈順序遍曆open表(根據f值進行排序),擴充讀取出來的節點,直到找到目標點。

其中getFGH就是計算該節點的f,g,h資訊。

你可以看到代碼裡面有寫著// 單調限制的注釋;再舉同一個例子說明一下。

廣州還擴充出一個節點:武漢。

武漢的f=5900,g=2400,h=3500。這時候是先擴充武漢,於是又找到了上海。

武漢到上海的距離是1900。這時候經過武漢到上海的節點資訊是g=2400+1900=4300,h是不變的也是3000。

上海節點mapNode之前儲存的g=3000,現在算出經過武漢到上海的距離是g=4300。因此經過武漢到上海比直接到上海的距離遠,因此不將f,g,h替換放到open表。

這就是單調限制。

下面是本篇文章代碼及示範程式的:



A*演算法的不足:

當目標點是位於死路地區,則A*演算法會遍曆整個地圖。這明顯是低效率的。


A*尋路演算法(曼哈頓距離)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.