A 演算法(一) 簡單實現

2021-08-02 13:36:29 字數 3576 閱讀 3936

最近準備參加海康威視的乙個軟體挑戰賽(需要用到路徑搜尋的演算法,參考了網上的一些案例,自己實現了乙個簡單的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.判斷元素是否填滿到指定大小,如果...