AStar算法
什么是AStar:
是一種靜態(tài)路網(wǎng)中求解最短路最有效的直接搜索方法,估價(jià)值跟實(shí)例值非常接近;
啟發(fā)式搜索 :
啟發(fā)式搜索就是在狀態(tài)空間中的搜索對(duì)每一個(gè)搜索的位置進(jìn)行評(píng)估,得到最好的位置,在從這個(gè)位置進(jìn)行搜索直到目標(biāo).這樣可以省略大量無(wú)謂的搜索路徑,提高了效率;
估價(jià)函數(shù) :
從當(dāng)前節(jié)點(diǎn)移動(dòng)到 目標(biāo)節(jié)點(diǎn)的預(yù)估費(fèi)用<費(fèi)用簡(jiǎn)單的說(shuō)就是從起點(diǎn)到終點(diǎn)的距離>(如果放到地圖上就是距離,走的路越多估價(jià)越高);這個(gè)估價(jià)就是啟發(fā)式的.在尋路問(wèn)題和迷宮問(wèn)題中,我們通常用曼哈頓(manhattan)估價(jià)函數(shù)預(yù)估費(fèi)用.
A*算法特點(diǎn):
在理論上是時(shí)間最優(yōu)的;
但也有缺點(diǎn):它的空間增長(zhǎng)是指數(shù)級(jí)別的;(格子越多計(jì)算的量也就越大)<優(yōu)化可以使用 二叉堆 >
中心思想:
通過(guò)從起始點(diǎn)開(kāi)始,檢查相鄰方格的方式,向外擴(kuò)展,直到找到目標(biāo);
運(yùn)用:
把一個(gè)平面分成一個(gè)個(gè)的小方格,方格分的越細(xì),尋路就越精準(zhǔn);
開(kāi)啟列表:
待檢查方格的集合列表,尋找周圍可以達(dá)到的點(diǎn),加入到此列表中,
并保存中心點(diǎn)為父節(jié)點(diǎn)
關(guān)閉列表:列表中保存不需要再次檢查的方格
路徑評(píng)分:
G-當(dāng)前點(diǎn)與起始點(diǎn)的距離
H-當(dāng)前點(diǎn)與目標(biāo)點(diǎn)的距離
F的值是G和F的和
F,G和H的評(píng)分被寫(xiě)在每個(gè)方格里.
如圖:F被打印在中間,G在左上角.H在右上角.
<如上圖>
從一個(gè)格子到相鄰格子的斜線距離(以為到斜線格子的距離為跟2,所以用1.4為單位)
從一個(gè)格子到相格子的直線距離(因?yàn)楦褡訛?,所以就以1為單位);
為了方便計(jì)算查看,都乘以10作為單位;
選擇路徑過(guò)程中,經(jīng)過(guò)哪個(gè)方格關(guān)鍵是:F=G+H;
<如上圖>以紅色格子為例
方塊的中心位置42就是估價(jià),也就是起始點(diǎn)到目標(biāo)的距離
左上角用G表示,也就是該格子到目標(biāo)點(diǎn)的距離為14
右上角用H表示,也就是該格子到起始點(diǎn)的距離為28
紅色格子右上角是62,是因?yàn)橐呀?jīng)確定了當(dāng)前紅色的格子,路徑是從當(dāng)前紅色格子到右上角的格子,所以值為62;
如果選擇的不是當(dāng)前紅色的格子,那么就會(huì)去改變其他格子的值,也就是說(shuō)每個(gè)格子的值隨著你的選擇進(jìn)行改變
(改變成符合當(dāng)前格子路徑上的值).
例如:從A到B的一個(gè)解析過(guò)程
開(kāi)始搜索:
1.把起始格添加到開(kāi)啟列表。
從A點(diǎn)開(kāi)始查找
2.尋找起點(diǎn)周圍所有可到達(dá)或者可通過(guò)的方格,把他們加入開(kāi)啟列表。
遍歷A所能到達(dá)的所有方格,把他們加入開(kāi)啟列表中
3.從開(kāi)啟列表中刪除點(diǎn)A,把它加入到一個(gè)“關(guān)閉列表”,列表中保存所有不需要再次檢查的方格。
因?yàn)锳已經(jīng)走過(guò),所以把A加入關(guān)閉列表中,下次在進(jìn)行遍歷時(shí)把A除外
繼續(xù)搜索:
4把當(dāng)前格子從開(kāi)啟列表中刪除,然后添加到關(guān)閉列表中。
因?yàn)橐呀?jīng)到達(dá)了當(dāng)前格子,所以把當(dāng)前格子放到關(guān)閉列表中(已經(jīng)到達(dá)了,沒(méi)有必要去進(jìn)行遍歷)
5檢查所有相鄰格子。跳過(guò)那些已經(jīng)在關(guān)閉列表中的或者不可通過(guò)的,把他們添加進(jìn)開(kāi)啟列表,把選中的方格作為新的方格的父節(jié)點(diǎn)。
當(dāng)前中的格子周圍有兩個(gè)已經(jīng)添加到開(kāi)啟列表中,上面三個(gè)為不可通過(guò),也就是障礙物,所以只是新添加了左側(cè)的兩個(gè)格子;
6如果某個(gè)相鄰格已經(jīng)在開(kāi)啟列表里了,檢查現(xiàn)在的這條路徑G值是否會(huì)更低一些。
如果新的G值更低,那就把相鄰方格的父節(jié)點(diǎn)改為目前選中的方格,重新計(jì)算F和G的值。
一旦重新選擇了一個(gè)點(diǎn)那么就需要重新計(jì)算一下當(dāng)前的費(fèi)用,上面寫(xiě)著只計(jì)算G和F的 值,為什么呢!
原因:
每個(gè)點(diǎn)到目標(biāo)點(diǎn)的距離是固定的,所以H點(diǎn)(又上角的點(diǎn))是不需要改變的,會(huì)變化的G值僅僅是因?yàn)槁方?jīng)改變的原因跟起始點(diǎn)的距離會(huì)發(fā)生改變,
所以只需要計(jì)算G的值和F的值,其他的點(diǎn)也會(huì)相應(yīng)的更新;
<圖一>
因?yàn)檫x擇的42,但是出現(xiàn)了3個(gè)相同的估價(jià),那么我們?cè)撛趺催x擇呢?
<圖二>
這里還有另外一個(gè)原則:那就是選擇一個(gè)距離目標(biāo)點(diǎn)最近的一個(gè)值,也就是H值最低的一個(gè).
也就是左側(cè)的48這個(gè)方塊 ,那么就把48這個(gè)點(diǎn)從開(kāi)啟列表中刪除,送進(jìn)關(guān)閉列表中.
因?yàn)檫x擇了48,新增了左側(cè)兩個(gè)點(diǎn),那么跟新一下在開(kāi)啟列表中的當(dāng)前48下面的兩個(gè)點(diǎn)(在這里下面那兩個(gè)點(diǎn)是沒(méi)有變化的,因?yàn)?2下面的也是48,所以路徑的值是沒(méi)有改變的);
那么繼續(xù)走
當(dāng)我們繼續(xù)走的時(shí)候,發(fā)現(xiàn)遍歷48所能達(dá)到的值,發(fā)現(xiàn)這條路徑不是最優(yōu)的.
為什么不是最優(yōu)的呢:(因?yàn)樵谒拈_(kāi)啟列表中還有一個(gè)48)
那么在他的開(kāi)啟列表中還有一個(gè)48的值,那么就把當(dāng)前的這個(gè)48從開(kāi)起列表中刪除,送進(jìn)關(guān)閉列表中。
我們就回到上一步,選擇42下方的48;
同理,這個(gè)48也不是最優(yōu)的,因?yàn)樗拈_(kāi)啟列表中還有一個(gè)48,那么我們繼續(xù)選擇42,右側(cè)的這個(gè)48;
結(jié)束
起始格下方格子的父節(jié)點(diǎn)已 經(jīng)和前面不同的。 之前它的G值是,并且指向 右上方的格子?,F(xiàn)在它的G 值是,指向它上方的格子。 這在尋路過(guò)程中的某處發(fā)生, 當(dāng)應(yīng)用新路徑時(shí),G值經(jīng)過(guò) 檢查變得低了-于是父節(jié)點(diǎn) 被重新指定,G和F值被重
新計(jì)算。
根據(jù)上述的原理得到如上圖所示的路徑,也就是最佳路徑;
總結(jié)
1把起始格添加到開(kāi)啟列表。
2重復(fù)如下的工作:
尋找開(kāi)啟列表中F值最低的格子。我們稱它為當(dāng)前格。
把它切換到關(guān)閉列表。
/1/對(duì)相鄰的格中的每一個(gè)–> 如果它不可通過(guò)或者已經(jīng)在關(guān)閉列表中,略過(guò)它。反之如下。如果它不在開(kāi)啟列表中,把它添加進(jìn)去。把當(dāng)前格作為這一格的父節(jié)點(diǎn)。記錄這一格的F,G,和H值。
/2/如果它已經(jīng)在開(kāi)啟列表中,用G值為參考檢查新的路徑是否更好。更低的G值意味著更好的路徑。如果是這樣,就把這一格的父節(jié)點(diǎn)改成當(dāng)前格,并且重新計(jì)算這一格的 G和F值。
停止,當(dāng)你 把目標(biāo)格添加進(jìn)了關(guān)閉列表,這時(shí)候路徑被找到–>沒(méi)有找到目標(biāo)格,開(kāi)啟列表已經(jīng)空了。這時(shí)候,路徑不存在。
3.保存路徑。從目標(biāo)格開(kāi)始,沿著每一格的父節(jié)點(diǎn)移動(dòng)直到回到起始格。
算法:步驟架構(gòu)
<1>開(kāi)啟集合
<2>關(guān)閉集合
<3>添加起始點(diǎn)到開(kāi)始集合中
<4>循環(huán)如下步驟: 當(dāng)前點(diǎn)=開(kāi)啟集合中最小F_Cost的點(diǎn) 將當(dāng)前點(diǎn)移出開(kāi)啟集合中 將當(dāng)前點(diǎn)添加到關(guān)閉集合中
<5>如果當(dāng)前點(diǎn)是目標(biāo)點(diǎn),結(jié)束查詢
<6>遍歷當(dāng)前點(diǎn)的每個(gè)相鄰點(diǎn) 如果相鄰點(diǎn)不能訪問(wèn)或者相鄰點(diǎn)在關(guān)閉集合中,跳過(guò)此相鄰點(diǎn) 如果新路徑到相鄰點(diǎn)的距離更短,或者相鄰點(diǎn)不在開(kāi)啟集合中 重新設(shè)置F_Cost 重新設(shè)置其父節(jié)點(diǎn)為當(dāng)前點(diǎn)
<7>如果相鄰點(diǎn)不在開(kāi)啟集合中
<8>添加相鄰點(diǎn)到開(kāi)啟集合什么是AStar: 是一種靜態(tài)路網(wǎng)中求解最短路最有效的直接搜索方法,估價(jià)值跟實(shí)例值非常接近;
啟發(fā)式搜索 : 啟發(fā)式搜索就是在狀態(tài)空間中的搜索對(duì)每一個(gè)搜索的位置進(jìn)行評(píng)估,得到最好的位置,在從這個(gè)位置進(jìn)行搜索直到目標(biāo).這樣可以省略大量無(wú)謂的搜索路徑,提高了效率;
在啟發(fā)式搜索中,對(duì)位置的估價(jià)是十分重要的.采用了不同的估價(jià),可以有不同的效果;
(估價(jià)函數(shù)就一種規(guī)則,制定的規(guī)則不同,最后的效果也就不同)<比如尋路的格子不同,最后的效果也是不同的>
估價(jià)函數(shù) :從當(dāng)前節(jié)點(diǎn)移動(dòng)到 目標(biāo)節(jié)點(diǎn)的預(yù)估費(fèi)用<費(fèi)用簡(jiǎn)單的說(shuō)就是從起點(diǎn)到終點(diǎn)的距離>(如果放到地圖上就是距離,走的路越多估價(jià)越高);這個(gè)估價(jià)就是啟發(fā)式的.在尋路問(wèn)題和迷宮問(wèn)題中,我們通常用曼哈頓(manhattan)估價(jià)函數(shù)預(yù)估費(fèi)用.
A*算法特點(diǎn):在理論上是時(shí)間最優(yōu)的;
但也有缺點(diǎn):它的空間增長(zhǎng)是指數(shù)級(jí)別的;(格子越多計(jì)算的量也就越大)<優(yōu)化可以使用 二叉堆 >
中心思想:通過(guò)從起始點(diǎn)開(kāi)始,檢查相鄰方格的方式,向外擴(kuò)展,直到找到目標(biāo);
.運(yùn)用
把一個(gè)平面分成一個(gè)個(gè)的小方格,方格分的越細(xì),尋路就越精準(zhǔn);
為了更好的描述,和理解A*算法提出的兩個(gè)概念(不存在于真實(shí)的場(chǎng)景中)
開(kāi)啟列表: 待檢查方格的集合列表,尋找周圍可以達(dá)到的點(diǎn),加入到此列表中,
并保存中心點(diǎn)為父節(jié)點(diǎn)
關(guān)閉列表:列表中保存不需要再次檢查的方格
路徑評(píng)分:
G-當(dāng)前點(diǎn)與起始點(diǎn)的距離
H-當(dāng)前點(diǎn)與目標(biāo)點(diǎn)的距離
F的值是G和F的和
F,G和H的評(píng)分被寫(xiě)在每個(gè)方格里.
如圖:F被打印在中間,G在左上角.H在右上角.
<如上圖>
從一個(gè)格子到相鄰格子的斜線距離(以為到斜線格子的距離為跟2,所以用1.4為單位)
從一個(gè)格子到相格子的直線距離(因?yàn)楦褡訛?,所以就以1為單位);
為了方便計(jì)算查看,都乘以10作為單位;
選擇路徑過(guò)程中,經(jīng)過(guò)哪個(gè)方格關(guān)鍵是:F=G+H;
<如上圖>以紅色格子為例
方塊的中心位置42就是估價(jià),也就是起始點(diǎn)到目標(biāo)的距離
左上角用G表示,也就是該格子到目標(biāo)點(diǎn)的距離為14
右上角用H表示,也就是該格子到起始點(diǎn)的距離為28
紅色格子右上角是62,是因?yàn)橐呀?jīng)確定了當(dāng)前紅色的格子,路徑是從當(dāng)前紅色格子到右上角的格子,所以值為62;
如果選擇的不是當(dāng)前紅色的格子,那么就會(huì)去改變其他格子的值,也就是說(shuō)每個(gè)格子的值隨著你的選擇進(jìn)行改變
(改變成符合當(dāng)前格子路徑上的值).
例如:從A到B的一個(gè)解析過(guò)程
開(kāi)始搜索:
1.把起始格添加到開(kāi)啟列表。
從A點(diǎn)開(kāi)始查找
2.尋找起點(diǎn)周圍所有可到達(dá)或者可通過(guò)的方格,把他們加入開(kāi)啟列表。
遍歷A所能到達(dá)的所有方格,把他們加入開(kāi)啟列表中
3.從開(kāi)啟列表中刪除點(diǎn)A,把它加入到一個(gè)“關(guān)閉列表”,列表中保存所有不需要再次檢查的方格。
因?yàn)锳已經(jīng)走過(guò),所以把A加入關(guān)閉列表中,下次在進(jìn)行遍歷時(shí)把A除外
繼續(xù)搜索:
4把當(dāng)前格子從開(kāi)啟列表中刪除,然后添加到關(guān)閉列表中。
因?yàn)橐呀?jīng)到達(dá)了當(dāng)前格子,所以把當(dāng)前格子放到關(guān)閉列表中(已經(jīng)到達(dá)了,沒(méi)有必要去進(jìn)行遍歷)
5檢查所有相鄰格子。跳過(guò)那些已經(jīng)在關(guān)閉列表中的或者不可通過(guò)的,把他們添加進(jìn)開(kāi)啟列表,把選中的方格作為新的方格的父節(jié)點(diǎn)。
當(dāng)前中的格子周圍有兩個(gè)已經(jīng)添加到開(kāi)啟列表中,上面三個(gè)為不可通過(guò),也就是障礙物,所以只是新添加了左側(cè)的兩個(gè)格子;
6如果某個(gè)相鄰格已經(jīng)在開(kāi)啟列表里了,檢查現(xiàn)在的這條路徑G值是否會(huì)更低一些。
如果新的G值更低,那就把相鄰方格的父節(jié)點(diǎn)改為目前選中的方格,重新計(jì)算F和G的值。
一旦重新選擇了一個(gè)點(diǎn)那么就需要重新計(jì)算一下當(dāng)前的費(fèi)用,上面寫(xiě)著只計(jì)算G和F的 值,為什么呢!
原因:每個(gè)點(diǎn)到目標(biāo)點(diǎn)的距離是固定的,所以H點(diǎn)(又上角的點(diǎn))是不需要改變的,會(huì)變化的G值僅僅是因?yàn)槁方?jīng)改變的原因跟起始點(diǎn)的距離會(huì)發(fā)生改變,
所以只需要計(jì)算G的值和F的值,其他的點(diǎn)也會(huì)相應(yīng)的更新;
<圖一>
因?yàn)檫x擇的42,但是出現(xiàn)了3個(gè)相同的估價(jià),那么我們?cè)撛趺催x擇呢?
<圖二>
這里還有另外一個(gè)原則:那就是選擇一個(gè)距離目標(biāo)點(diǎn)最近的一個(gè)值,也就是H值最低的一個(gè).
也就是左側(cè)的48這個(gè)方塊 ,那么就把48這個(gè)點(diǎn)從開(kāi)啟列表中刪除,送進(jìn)關(guān)閉列表中.
因?yàn)檫x擇了48,新增了左側(cè)兩個(gè)點(diǎn),那么跟新一下在開(kāi)啟列表中的當(dāng)前48下面的兩個(gè)點(diǎn)(在這里下面那兩個(gè)點(diǎn)是沒(méi)有變化的,因?yàn)?2下面的也是48,所以路徑的值是沒(méi)有改變的);
那么繼續(xù)走
當(dāng)我們繼續(xù)走的時(shí)候,發(fā)現(xiàn)遍歷48所能達(dá)到的值,發(fā)現(xiàn)這條路徑不是最優(yōu)的.
為什么不是最優(yōu)的呢:(因?yàn)樵谒拈_(kāi)啟列表中還有一個(gè)48)
那么在他的開(kāi)啟列表中還有一個(gè)48的值,那么就把當(dāng)前的這個(gè)48從開(kāi)起列表中刪除,送進(jìn)關(guān)閉列表中。
我們就回到上一步,選擇42下方的48;
同理,這個(gè)48也不是最優(yōu)的,因?yàn)樗拈_(kāi)啟列表中還有一個(gè)48,那么我們繼續(xù)選擇42,右側(cè)的這個(gè)48;
結(jié)束
起始格下方格子的父節(jié)點(diǎn)已 經(jīng)和前面不同的。 之前它的G值是,并且指向 右上方的格子?,F(xiàn)在它的G 值是,指向它上方的格子。 這在尋路過(guò)程中的某處發(fā)生, 當(dāng)應(yīng)用新路徑時(shí),G值經(jīng)過(guò) 檢查變得低了-于是父節(jié)點(diǎn) 被重新指定,G和F值被重
新計(jì)算。
根據(jù)上述的原理得到如上圖所示的路徑,也就是最佳路徑;
總結(jié)
1把起始格添加到開(kāi)啟列表。
2重復(fù)如下的工作:
尋找開(kāi)啟列表中F值最低的格子。我們稱它為當(dāng)前格。
把它切換到關(guān)閉列表。
/1/對(duì)相鄰的格中的每一個(gè)–> 如果它不可通過(guò)或者已經(jīng)在關(guān)閉列表中,略過(guò)它。反之如下。如果它不在開(kāi)啟列表中,把它添加進(jìn)去。把當(dāng)前格作為這一格的父節(jié)點(diǎn)。記錄這一格的F,G,和H值。
/2/如果它已經(jīng)在開(kāi)啟列表中,用G值為參考檢查新的路徑是否更好。更低的G值意味著更好的路徑。如果是這樣,就把這一格的父節(jié)點(diǎn)改成當(dāng)前格,并且重新計(jì)算這一格的 G和F值。
停止,當(dāng)你 把目標(biāo)格添加進(jìn)了關(guān)閉列表,這時(shí)候路徑被找到–>沒(méi)有找到目標(biāo)格,開(kāi)啟列表已經(jīng)空了。這時(shí)候,路徑不存在。
3.保存路徑。從目標(biāo)格開(kāi)始,沿著每一格的父節(jié)點(diǎn)移動(dòng)直到回到起始格。
算法:步驟架構(gòu)
<1>開(kāi)啟集合
<2>關(guān)閉集合
<3>添加起始點(diǎn)到開(kāi)始集合中
<4>循環(huán)如下步驟: 當(dāng)前點(diǎn)=開(kāi)啟集合中最小F_Cost的點(diǎn) 將當(dāng)前點(diǎn)移出開(kāi)啟集合中 將當(dāng)前點(diǎn)添加到關(guān)閉集合中
<5>如果當(dāng)前點(diǎn)是目標(biāo)點(diǎn),結(jié)束查詢
<6>遍歷當(dāng)前點(diǎn)的每個(gè)相鄰點(diǎn) 如果相鄰點(diǎn)不能訪問(wèn)或者相鄰點(diǎn)在關(guān)閉集合中,跳過(guò)此相鄰點(diǎn) 如果新路徑到相鄰點(diǎn)的距離更短,或者相鄰點(diǎn)不在開(kāi)啟集合中 重新設(shè)置F_Cost 重新設(shè)置其父節(jié)點(diǎn)為當(dāng)前點(diǎn)
<7>如果相鄰點(diǎn)不在開(kāi)啟集合中
<8>添加相鄰點(diǎn)到開(kāi)啟集合
總結(jié)
- 上一篇: 王者荣耀是用什么代码变成MOBA游戏的,
- 下一篇: 拼音汉字映射表