重要公式:f(n
)=g(
n)+h
(n
)f(n)=g(n)+h(n)
f(n)=g
(n)+
h(n)
其中:a*演算法在運算過程中,每次從優先佇列中選取f(n)值最小(優先順序最高)的節點作為下乙個待遍歷的節點。
另外,a*演算法使用兩個集合來表示待遍歷的節點,與已經遍歷過的節點,這通常稱之為open_set
和close_set
。
完整的a*演算法描述如下:
* 初始化open_set和close_set;
* 將起點加入open_set中,並設定優先順序為0(優先順序最高);
* 如果open_set不為空,則從open_set中選取優先順序最高的節點n:
* 如果節點n為終點,則:
* 從終點開始逐步追蹤parent節點,一直達到起點;
* 返回找到的結果路徑,演算法結束;
* 如果節點n不是終點,則:
* 將節點n從open_set中刪除,並加入close_set中;
* 遍歷節點n所有的鄰近節點:
* 如果鄰近節點m在close_set中,則:
* 跳過,選取下乙個鄰近節點
* 如果鄰近節點m也不在open_set中,則:
* 設定節點m的parent為節點n
* 計算節點m的優先順序
* 將節點m加入open_set中
啟發函式
上面已經提到,啟發函式會影響a*演算法的行為。
由上面這些資訊我們可以知道,通過調節啟發函式我們可以控制演算法的速度和精確度。因為在一些情況,我們可能未必需要最短路徑,而是希望能夠盡快找到乙個路徑即可。這也是a*演算法比較靈活的地方。
對於網格形式的圖,有以下這些啟發函式可以使用:
1,q:從當前節點的周圍節點中如何選取第乙個檢查節點?
a:具有最小 f 值的那個。
/**
* a*演算法簡易版實現
* @author ***
* */
public
class
astar,,
,,,,
};mapinfo info=
newmapinfo
(maps,maps[0]
.length, maps.length,
newnode(1
,6),
newnode(4
,3))
; starttime = system.
currenttimemillis()
;start
(info)
;printmap
(maps)
; endtime = system.
currenttimemillis()
- starttime;
system.out.
println
(+ endtime);}
public
static
void
start
(mapinfo mapinfo)
/** * 如果不一致的話
* 1,將當前節點(起點)從open_list彈出,並加入到close_list中
* 2,將當前節點(起點)周圍的節點加入到open_list來【不可達節點不用加,已在open_list中的節點不用加,已在close_list中的節點不用加】,並且重新計算g和f值
*/// node current = open_list.poll();
// close_list.add(current);
while
(!open_list.
isempty()
)// 彈出當前節點加入到close_list中
node current = open_list.
poll()
; close_list.
add(current)
;// 將當前節點的周圍節點新增到open_list中
// 上
addnode2open
(mapinfo, current,current.coord.x,current.coord.y+
1,direct_value)
;// 右
addnode2open
(mapinfo, current,current.coord.x+
1,current.coord.y,direct_value)
;// 下
addnode2open
(mapinfo, current,current.coord.x,current.coord.y-
1,direct_value)
;// 左
addnode2open
(mapinfo, current,current.coord.x-
1,current.coord.y,direct_value)
;// 左上
addnode2open
(mapinfo, current,current.coord.x-
1,current.coord.y+
1,oblique_value)
;// 右上
addnode2open
(mapinfo, current,current.coord.x+
1,current.coord.y+
1,oblique_value)
;// 右下
addnode2open
(mapinfo, current,current.coord.x+
1,current.coord.y-
1,oblique_value)
;// 左下
addnode2open
(mapinfo, current,current.coord.x-
1,current.coord.y-
1,oblique_value);}
}/**
* 在二維陣列中繪製路徑
*/private
static
void
drawpath
(string[
] maps, node end)
}/**
* 將周圍的鄰節點加入到open_list中,並且重新計算g和f值
* 按照:上->右->下->左 左上->右上->右下->左下的順序依次新增
* @param end
* @param current
* @param x
* @param y
* @param value
*/public
static
void
addnode2open
(mapinfo mapinfo, node current,
int x,
int y,
int value)
else
open_list.
add(child);}
else
if(child.g > g)}}
/** * 判斷結點能否放入open列表:
* 1,不再地圖中的節點不要放
* 2,不可達的節點不要放
* 3,在close_list中的節點不要放
*/private
static
boolean
canaddnodetoopen
(mapinfo mapinfo,
int x,
int y)
/** * 判斷座標是否在close表中
*/private
static
boolean
iscoordinclose
(coord coord)
/** * 判斷座標是否在close表中
*/private
static
boolean
iscoordinclose
(int x,
int y)
}return
false;}
/** * 從open列表中查詢結點
*/private
static node findnodeinopen
(coord coord)
}return null;
}/**
* 計算h的估值:「曼哈頓」法,座標分別取差值相加
*/private
static
intcalch
(coord end,coord coord)
/** * 判斷結點是否是最終結點
*/private
static
boolean
isendnode
(coord end,coord coord)
/** * 列印地圖
*/public
static
void
printmap
(string[
] maps)
system.out.
println()
;}}}
關於MRu演算法的實現研究
class clistnode clistnode void close void setnodedata void pdata void setnodenext clistnode plistnode void setnodebefore clistnode plistnode void getn...
關於遞推演算法的研究
遞迴基礎 程式呼叫自身的程式設計技術稱為遞迴 recursion 遞迴作為一種演算法在程式語言中廣泛應用 乙個過程或函式在其定義或者說明中有直接或間接呼叫自身的一種方法,它通常把乙個大型複雜的問題層層轉化為乙個與原問題相似規模較小的問題來求解 遞迴策略只需少量的程式就可描述出解題過程所需要的多次重複...
關於A 演算法的一些研究
公式 f g h 代價計算,尋路代價最小的就是我們要找的 g 表示從起點 a 移動到網格上指定方格的移動耗費 可沿斜方向移動 h 表示從指定的方格移動到終點 b 的預計耗費 h 有很多計算方法,這裡我們設定只可以上下左右移動 下面拿個例子說明一下 原文參考 假如從a尋路到b 尋路步驟 1.從起點a開...