日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

搜索 —— 启发式搜索 —— A* 算法

發(fā)布時(shí)間:2025/3/17 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 搜索 —— 启发式搜索 —— A* 算法 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

【概述】

A*(A-Star)算法是一種在靜態(tài)路網(wǎng)中,求解最短路的最有效的直接搜索方法,也是解決許多搜索問(wèn)題的有效算法之一。

A* 算法實(shí)際上是對(duì) Dijkstra 算法的優(yōu)化后得到的,關(guān)于 Dijkstra 算法:點(diǎn)擊這里

A*算法在程序設(shè)計(jì)競(jìng)賽中,一般用于解決 k 短路問(wèn)題,關(guān)于 k 短路問(wèn)題:點(diǎn)擊這里

【原理】

在 Dijkstra 算法中,我們借助優(yōu)先隊(duì)列來(lái)實(shí)現(xiàn),每次從優(yōu)先隊(duì)列中取出結(jié)點(diǎn),再?gòu)倪@個(gè)結(jié)點(diǎn)擴(kuò)散到其他結(jié)點(diǎn),而優(yōu)先隊(duì)列的優(yōu)先依據(jù)是根據(jù)起點(diǎn)到隊(duì)列中結(jié)點(diǎn)最近的一個(gè),即隊(duì)列中的結(jié)點(diǎn)離起始點(diǎn)最近的會(huì)先出隊(duì)。

但不可避免的是,Dijkstra 存在跑偏問(wèn)題,如下圖,若起點(diǎn)為 1 號(hào)點(diǎn),終點(diǎn)為 6 號(hào)點(diǎn),首先一定會(huì)走 3、4 號(hào)點(diǎn),這肯定不是最佳路徑,一開始就跑偏了。

在 Dijkstra 算法中,判斷的依據(jù)只是已知的起點(diǎn)到某點(diǎn) i 的距離 G(i),那么我們可以增加一個(gè)判斷量來(lái)減少跑偏的概率。

如果能夠計(jì)算當(dāng)前點(diǎn) i 到終點(diǎn)的距離,再結(jié)合 G(i),那么可以防止過(guò)度跑偏,但這個(gè)距離是未知的,因此我們可以設(shè)置一個(gè)估值,即啟發(fā)函數(shù) H(i)

啟發(fā)函數(shù) H(i) 的設(shè)置是 A* 算法關(guān)鍵,如何設(shè)置這個(gè)啟發(fā)函數(shù)影響到算法的性能,在得到了啟發(fā)函數(shù)后,我們就有了最終的估價(jià)函數(shù) F(i)=G(i)+H(i),在優(yōu)先隊(duì)列中,以這個(gè)估價(jià)函數(shù)作為指標(biāo)進(jìn)行出隊(duì)。

一般來(lái)說(shuō),在二維平面圖中,我們將圖置于坐標(biāo)軸中,通過(guò)計(jì)算結(jié)點(diǎn)間的歐幾里得距離來(lái)得到兩點(diǎn)間的直線距離,這個(gè)距離即可作為當(dāng)前點(diǎn) i 到終點(diǎn)距離的估值。但歐幾里得距離的計(jì)算要進(jìn)行開方,較為復(fù)雜,一般通過(guò)加減法來(lái)計(jì)算簡(jiǎn)單的曼哈頓距離來(lái)代替歐幾里得距離,作為啟發(fā)函數(shù) H(i)。

而在一般圖中,我們通常是建立反圖,跑一次最短路算法,將得到每個(gè)點(diǎn)到 t?的最短路的距離 dis[i] 作為啟發(fā)函數(shù) H(i)

【實(shí)現(xiàn)】

struct Edge {int to, next;int w;Edge() {}Edge(int to, int next, int w) : to(to), next(next), w(w) {} }; struct Map {int tot;int head[N];Edge edge[N * N];Map() {tot = 0;memset(head, -1, sizeof(head));}void addEdge(int x, int y, int w) {edge[++tot].to = y;edge[tot].next = head[x];edge[tot].w = w;head[x] = tot;}Edge &operator[](int pos) { return edge[pos]; } }; int n, m; Map G, GT; int dis[N]; bool vis[N]; struct Status{int node;//點(diǎn)編號(hào)int diss;//距離int priority;//優(yōu)先級(jí)Status() : node(0), diss(0), priority(dis[0]) {}Status(int node, int diss) : node(node), diss(diss), priority(diss + dis[node]) {}bool operator<(Status b) const { return priority > b.priority; } } status; bool SPFA(int S, int T) { //對(duì)反圖求最短路memset(dis, INF, sizeof(dis));memset(vis, false, sizeof(vis));dis[S] = 0;queue<int> Q;Q.push(S);while (!Q.empty()) {int x = Q.front();Q.pop();vis[x] = false;for (int i = GT.head[x]; i != -1; i = GT[i].next) {int y = GT[i].to;if (dis[x] + GT[i].w < dis[y]) {dis[y] = dis[x] + GT[i].w;if (!vis[y]) {Q.push(y);vis[y] = true;}}}}return dis[T] != INF; } int AStar(int S, int T) {priority_queue<Status> Q;Q.push(Status(S, 0));while (!Q.empty()) {Status temp = Q.top();Q.pop();if (temp.node == T)return temp.diss;for (int i = G.head[temp.node]; i != -1; i = G[i].next)if (temp.diss + G[i].w < temp.diss)Q.push(Status(G[i].to, temp.diss + G[i].w));}return -1; } int main() {scanf("%d%d", &n, &m);for (int i = 1; i <= m; i++) {int x, y, w;scanf("%d%d%d", &x, &y, &w);G.addEdge(x, y, w);GT.addEdge(y, x, w);}int s, t;scanf("%d%d", &s, &t);if (!SPFA(t, s))printf("-1\n");elseprintf("%d\n", AStar(s, t));return 0; }

?

總結(jié)

以上是生活随笔為你收集整理的搜索 —— 启发式搜索 —— A* 算法的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。