最近準備參加海康威視的乙個軟體挑戰賽(需要用到路徑搜尋的演算法,參考了網上的一些案例,自己實現了乙個簡單的a*演算法。
a*演算法是一種啟發式的路徑搜尋演算法。對於地圖中的每乙個節點,我們記錄起點到該節點的消耗g,估算該節點到終點的消耗h(並不是準確值,有多種估算方法,簡單的比如歐氏距離),已經兩者之和f=g+h。
具體步驟為:
①將起點放入openlist;
②從openlist中選取f值最小的節點,記為v;
③將節點v從openlist中移除,加入closelist中;
④遍歷節點v周圍的節點,記為k,判斷k其是否已經加入了closelist:
k沒有加入closelist:
k是否加入了openlist:
是:如果其通過節點v距離更近(即v.g+distance(v,k) < k.g),記錄k的父節點為v
否:將k加入openlist,設定其父節點為v
k加入了closelist:
無操作⑤重複②到④,知道遇到終點;
⑥從終點尋找其父節點,直到起點,得到了終點到起點的路徑。
其流程為
把起始格新增到 "開啟列表"
do
if (它不在開啟列表中)
把它新增進 "開啟列表", 把當前格作為這一格的父節點, 計算這一格的 fgh
if (它已經在開啟列表中)
}} while( 目標格已經在 "開啟列表", 這時候路徑被找到)
如果開啟列表已經空了, 說明路徑不存在.
最後從目標格開始, 沿著每一格的父節點移動直到回到起始格, 這就是路徑.
以下給出具體實現的**(這部分**沒有經過優化,執行很慢,但是能正確實現a*演算法的功能):
其中,"maputils.h"中定義了:二位陣列parkmap表示地圖,imaplength表示地圖長度,imapwidth表示地圖寬度。
astarutils.h
// by 2023年5月27日20:19:49
#ifndef _a_star_utils_h_
#define _a_star_utils_h_
#include struct point
point(int _x, int _y) :x(_x), y(_y)
{} int x; // 點的橫座標,從0開始
int y; // 點的縱座標,從0開始
};struct listnode
listnode(point p, int f, int g, int h) :position(p), f(f), g(g), h(h), parentposition(0, 0), hasparent(false)
{} point position;
int f = 0; // f = g + h
int g = 0; // 起點到該店的移動代價(已經走過的路程)
int h = 0; // 該點到終點的估算成本(直接去橫縱座標差之和)
point parentposition;
bool hasparent;
};class astar;
#endif
astarutils.cpp
// by denghaijin 2023年5月27日20:20:26
#include "astarutils.h"
#include "maputils.h"
std::vectorastar::findpathinmap(int start_x, int start_y, int dest_x, int dest_y, bool & succeed)
if (parkmap[cur_y][cur_x].mark == *"x")
else}}
}} // 右邊的點
if (node_min_f->position.x < imaplength - 1)
if (parkmap[cur_y][cur_x].mark == *"x")
else}}
}} // 上邊的點
if (node_min_f->position.y > 0)
if (parkmap[cur_y][cur_x].mark == *"x")
else}}
}} // 下邊的點
if (node_min_f->position.y < imapwidth - 1)
if (parkmap[cur_y][cur_x].mark == *"x")
else}}
}} //判斷是否結束
// 終點加入openlist
//if (findnodeinopenlist(point(dest_x, dest_y)) != null)
// stop = true;
// 查詢終點失敗,並且 open list 是空的,此時沒有路徑
// ...
} // temp
std::vectorreverselist;
listnode * curnode = findnodeincloselist(point(dest_x, dest_y));
while (curnode != null && curnode->position.x != start_x || curnode->position.y != start_y)
std::vectorlist;
for (int index = reverselist.size() - 1; index >= 0; index--)
return list;
}listnode * astar::findleastfinopenlist()
} return res_node;
}bool astar::isnodeinopenlist(listnode * node)
} return false;
}bool astar::isnodeincloselist(listnode * node)
} return false;
}listnode * astar::findnodeinopenlist(point p)
} return null;
}listnode * astar::findnodeincloselist(point p)
} return null;
}void astar::removenodefromopenlist(point p) }}
void astar::removenodefromcloselist(point p)
}}
推薦演算法簡單實現
coding utf 8 import random 乙個使用者的標籤行為一般由乙個三元組組成 使用者,物品,標籤 即使用者u給物品i打上了b標籤。1.統計每個使用者最常用標籤 2.對於每個標籤,統計被打過這個標籤次數最多的物品 3.對於乙個使用者,找到他常用的標籤,從而找到具有這些標籤的熱門物品進...
A 演算法C 簡單實現
一.演算法步驟 1.初始化圖,openlist,closedlist 2.將起點加入openlist,3.在openlist中尋找啟發函式值f g h最小的節點v,4.將v從openlist中刪除,5.將從openlist中刪除的節點v加入closedlist 6.對於節點v周圍的8個節點v1而言 ...
簡單實現演算法LRU
lru的主要思想基本是,設定乙個固定大小的容器,不斷新增元素。當容器放滿時,把最前面的元素清除,在對尾新增新元素,如果元素是重複的元素,則找出那個元素放到隊尾。lru演算法主要步驟是 1.判斷新元素的key是否在lru中,如果在,就把此元素找出來然後拿到鍊錶尾部 2.判斷元素是否填滿到指定大小,如果...