使用prim演算法生成隨機迷宮

2021-09-12 01:36:51 字數 2253 閱讀 5946

三、prim演算法和迷宮生成

1.我們將迷宮定義如下:迷宮由道路組成,且迷宮中道路上的任意兩點應互相可達

2.隨機迷宮生成演算法一般有以下三種,這裡只介紹隨機prim演算法

最小生成樹:在帶權圖g=( v,e )中(v為點集,e為邊集且每條邊帶有權值),我們希望找到e的乙個無環子集t,使得v中任意兩點可達。由於t無環且聯通所有點,可知t必為一顆樹,稱這種邊子集t為生成樹,稱所有滿足條件的t中權值和最小的為最小生成樹

舉例來說,我們繪製一塊pcb電路板,需要把n個針腳佈線連線在一起,並希望連線長度總和最小。這裡n個針腳即為點集,任意兩針腳間的所有可能連線組成這個pcb圖的邊集,而連線的長度可看做該線的權值。任意乙個連線所有針腳且不產生連線回環的連法都是此pcb圖的乙個生成樹,所有生成樹中用線長度最短的即為最小生成樹.

prim是求給定若干點間最小生成樹的經典演算法。另一種此問題的經典演算法是kruskal演算法

prim演算法使用的是貪心策略,其正確性可以證明。

演算法流程如下:

使用迴圈不變式來證明演算法正確性,關於迴圈不變式可以參考:迴圈不變式的思想及其應用

prim演算法要管理的集合a遵循以下迴圈不變式:在每遍迴圈前,a是某最小生成樹的乙個子集。也就是說,我們要在每一步迴圈找到乙個邊(u,v),使得 a∪也是某最小生成樹的子集,我們可以定義滿足這個要求的邊為安全邊按以下方式使用迴圈不變式證明正確性

1   a=∅

2while a不是最小生成樹

3 找到安全邊(u,v)

4 a=a∪

5return a

初始化:在第一行後,a直接滿足迴圈不變式

保持:演算法第2~4行一直加入安全邊,不會破壞迴圈不變式

終止:所有加入a的邊都屬於某最小生成樹,則第5行返回的a一定是乙個最小生成樹

上述策略的重點在於第3行,如何找到一條安全邊。(這條安全邊是必然存在的,因為迴圈不變式告訴我們一定存在乙個最小生成樹t滿足a∈t,2~4行時a是t的真子集,一定有邊(u,v)∈ t && (u,v)∉ a,此邊即為安全邊)

為了辨別安全邊,先證明以下定理:

設t是包含a的乙個最小生成樹,有切割(s,v-s)尊重a,它的輕量級邊為(u,v)

∵t為乙個最小生成樹,連通圖中任意兩點

∴點u,v間存在簡單路徑p∈t

∵點u,v分處於切割兩側

∴必存在邊(x,y)∈ p且橫跨切割(s,v-s)

∵t中無環,p唯一

∴刪除邊(x,y)會使t被分解為兩個連通分量

∴將(u,v)加入這兩個連通分量可以生成新的生成樹t'

∵權值w(

(u,v)

)<=w(

(x,y)

)∴w(t')

<=w(t)

∴t'也是最小生成樹

∵切割(s,v-s)尊重a

∴(x,y)∉ a

又∵a∈t

∴a∈t'

∴a∪∈t'

∴(u,v)是a的安全邊

進一步證明以下推論:

∵切割(vc,v-vc)尊重集合a

又∵(u,v)是橫跨此切割的一條輕量級邊

∴由以上定理,(u,v)對a安全

prim演算法和kruskal演算法是對於這一推論的兩個應用形式。對於prim演算法,可以認為初始化時ga中的連通分量包括初始邊和剩下的n-2個點,ga中除了這個初始邊不斷變大,其他樹都是根節點狀態。每次迴圈加入一條和a相鄰的權值最小的邊,實際就是在森林ga中選乙個最近的根節點狀態的樹加入那個大樹中,直到所有點都加入為止。

通過如下方法將迷宮生成問題和求最小生成樹建立聯絡:

具體落實到程式設計上

讓迷宮全是牆.

選乙個單元格作為迷宮的通路,然後把它的鄰牆放入列表

當列表裡還有牆時

從列表裡隨機選乙個牆,如果這面牆分隔的兩個單元格只有乙個單元格被訪問過,那就從列表裡移除這面牆,即把牆打通,讓未訪問的單元格成為迷宮的通路,再把這個格仔的牆加入列表

如果牆兩面的單元格都已經被訪問過,那就從列表裡移除這面牆

列表裡已經沒有牆了,結束

三種迷宮生成演算法概述,這篇文章裡關於prim的描述我覺得更接近克魯斯卡爾演算法

三大迷宮生成演算法 ,這篇文章裡有示例**供參考

Prim迷宮演算法 隨機迷宮生成

最近在學android開發,老師讓我們自己做個應用,我就想做個簡單的roguelike rpg小遊戲。由於要用到迷宮,所以在網上學習了一下prim迷宮演算法,先用c 手擼了乙個簡單的模板。隨機選擇乙個白色格仔 i,j 實際位置為i 2 1,j 2 1 作為當前正在訪問的格仔,同時把該格仔放入乙個已經...

演算法 隨機生成迷宮

演算法原理 從起點開始,隨機選擇乙個方向移動,一直移動到終點,則移動的路徑便是迷宮的路徑。移動過程中要保證路徑不要相交,不要超出邊界,生成效果 public partial class mainform form void btncreateclick object sender,eventargs...

隨機生成迷宮

首先初始地圖所有位置均設為障礙牆,然後任意插入乙個牆體進牆佇列 再判斷此時牆體是否可以設定為路 判斷依據 上下左右四個位置是否只有乙個位置是路 若設定為路,則將該位置四周所有的牆插入佇列 若無法設定為路,直接從牆佇列中刪去當前結點所在的節點,若牆佇列不為空,則從佇列中隨機選取一處障礙重新執行,重複以...