dijkstra演算法 c 演算法思維

2021-10-13 18:02:49 字數 3359 閱讀 7388

啟發式思維:

歷史啟發。歷史計算過的值對計算當前值有啟發作用。比如常見遞推式、動態規劃演算法。

這也是常見的遞迴思維。

2. 字首、中綴、字尾啟發,固定的前中字尾會對計算有啟發。固定的前中字尾是乙個集合,相當於對問題進行了劃分(分割思維),固定住了某個維度,問題變得簡單清晰。如lis中,字首分析中,固定a[i],所有以a[i]結束的最長遞增序列。分解成最後乙個數字對結果有沒有貢獻兩種情況。也就是把lis(i)分解成max。a[i]無貢獻:lis(i-1)規模減小,a[i]有貢獻:lis(i)且已a[i]結尾,條件增強。

3. 規則啟發。客觀規則對計算當前值有啟發作用,比如數學規則(數學公理定義定理)、對稱性限制等等(manacher演算法)。強規則限制,人無法改變,比如邏輯、數學等等。

4. 背景啟發。在特定領域內的規則對計算有啟發作用。比如物理規則、人為制定的規則等等。典型演算法:a*啟發搜尋。弱規則限制,人可以改變。

5. 相似性啟發。主要靠聯想和抽象。表象上完全不同的東西,抽象之後可能會有相似的結構。 比較強的相似性就是1-1對映轉換空間。

6. 跨領域啟發。比如生物啟發計算機。

遞迴思維:

當前的項是由前面幾項通過一定規則構造出來的。問題向前/向後走一步問題和上一步是相識的,只是規模有變化,沒有超出我們對問題的定義。

結構遞迴:比如二叉樹就是遞迴定義的,每乙個單元有相似的結構。整體是由這個基本結構組成的。

過程遞迴:整個序列是由固定的規則生成的。比如漢諾塔。

分割思維:

一次分割(劃分)相當於創造了新的秩序,使原先混沌的東西逐漸秩序化。通過應用規則,來簡化問題。劃分之後的結構可以給我一些啟發(比如這個區域的東西如何改變才能去另乙個區域)或者可以各個擊破。比如dijkstra演算法。分割要要注意分割的完備性(不要有漏掉的東西)。

不斷對劃分後的集合進行劃分(過程遞迴),最後的結果會形成一棵樹。

轉換思維:

把乙個問題1-1對映到另一領域,使得問題變得容易解決**換之後的領域**(定理)多)。最典型的就是積分變換(傅利葉變換、拉普拉斯變換等等)、隱式圖演算法。

簡化思維:

想辦法簡化目標問題。強化或者弱化目標條件、分步驟向目標進行,比如求最大平均值,我們可以先求均值,在求最大。簡化依賴項(比如依賴前n項簡化為依賴前1項)。

打破思維:

發現核心的模式,即發現一類演算法中共同的部分,要突破某個界限(如時間複雜度),必須修改核心模式。例如一般排序都需要交換位置(核心是交換),只要使用交換元素的方法,就無法打破o(nlogn)的下界,計數排序則不使用交換,這樣就突破了普通排序時間複雜度o(nlogn)的下界。要突破某個界限,需要打破原有的思路,需求新方法。

直線思維:

最直接最簡單最暴力的方式求解。直線演算法不能滿足需要的時候,我們要考慮其它路徑。

演算法中的常用模式:

一般次序:分治,貪心,遞迴,回溯,動態規劃,隱式樹,隱式圖。

馬爾可夫模型:

,乙個序列中,當前項僅依賴後面一項。即

對 來說是充分的。

廣義馬爾可夫模型:

,即當前項依賴前面的多項。如果把多項看做1項就是馬爾可夫模型,

。抽象出問題相關的變數。大膽假設,小心求證。

確定核心狀態(可能是多維的),狀態需要根據情況自定義。比如固定了哪些維度,問題就會簡單很多(看得更清楚)。

確定轉移方程。

使用快取,降低時空複雜度。

動態規劃的核心是:從整體考慮,髮型最優子結構,減小問題規模。即當前整體分解為子整體的構造過程,並且這個過程能證明最後的結果(充分性)。對於較複雜的問題,往往要找到好的狀態、維度,分割定義域,用高維陣列關聯多個特徵(維度)等等思路。

動態規劃:一般是微觀+巨集觀的思維模式。微觀:如果給不確定的系統在某個位置給出某個值(這個值容易算出),這個點出現之後,巨集觀的結構方式變化:1.問題規模減小,結構一樣。2.問題規模不變,條件增加。即原問題變為各個子問題之和。

分治:劃分定義域,分別處理。分情況討論。

遞迴:往往是結構遞迴。發現結構相似性。

回溯: 往往是dfs。

演算法思考的一般步驟:

典型問題,已有方法 -> 轉換簡化成已有方法 -> 分治 -> 貪心 -> 動規 -> 隱式圖(樹)->

思路要清晰,論證要充分

圖的特點:

圖和線性結構(鍊錶)的最大區別是:圖在在當前時刻只能看到區域性(相鄰的部分),線性結構隨時可以看到整體。如果某一情況下,我們只能到達(看到)某個區域性(鄰接點)那就可以作為圖來處理(隱式圖或樹(只有乙個爸爸))。

在圖中我們想要看到整體,就必須通過各種形式的遍歷方法來實現。如dfs/bfs,其它演算法可以看做是dfs/bfs的變形和深化。其實思路都差不多,就是挨個挨個訪問,不斷做劃分。

dfs在深度維度上的劃分,就是按照深度的一直遍歷完,圖可以劃分為:完全訪問過的分支,部分訪問的分支,沒有訪問的分支。

bfs在廣度維度上的劃分,變種有dijkstra,bellmanford,a*。優先訪問最臨近的一層。訪問的資訊是按層給定的。純bfs,圖可劃分為:完全訪問過的層,部分訪問的層,沒有訪問的層。

例子:lcs(最長公共子串行):

# eg. s1= "hellzo",s2= "ahebllco" -> 5

# 變數:i:s1的第i個字元, j:s2的第j個字元

# 狀態:c[i][j] , 遍歷到s1的第i個字元,s2的第j個字元時最長的公共子串行長度。關聯i,j兩個維度。

# 轉移方程: c[i][j]的構造過程,

# c[i][j] = {

# c[i-1][j-1]+1 if x[i]=y[j] 0<=ilis(最長遞增子串行):

# eg. [5,1,3,2,4,5,1] -> 4

# 維度: b[i]是以a[i]結尾的最長遞增子串行的長度。

# 轉移方程:b[i] = b[j]+1 ; j = argmax{b[j] | a[i]>=a[j] and j=a[j])子串。

def lis(arr):

n = len(arr)

b = [1 for _ in range(n)]

mb, mi = 0,0

for i in range(n):

for j in range(i): # 最長可行子串

if arr[i]>=arr[j]:

if b[j]+1>b[i]:

b[i] = b[j]+1

if b[i]> mb:

mb,mi = b[i],i

return mb

Dijkstra演算法 C 實現

對於圖g v,e 給定源點 s 屬於 v 單源路徑是指從 s 到圖中其他各頂點的最短路徑.下圖為帶權有向圖,從 v0 到其餘各個頂點的最短路徑如表所示。源點終點 最短路徑 路徑長度 v0v1 v0 v1 12v2 v0 v2 10v3 v0 v4 v3 50v4 v0 v4 30v5 v0 v4 v...

c語言Dijkstra演算法

include dijkstra演算法 解決最短路徑問題,從乙個初始點v0出發,設定lowcost陣列,記錄初始點到每乙個頂點的最短路徑,設定path陣列 記錄初始點到每個點最短路徑所經過的每乙個點,設定visit陣列,記錄已經選入lowcost陣列的點設定為 1 下次經過不再選中。思想 選擇初始點...

Dijkstra演算法(C語言)

dijkstra演算法 1.定義概覽 dijkstra 迪傑斯特拉 演算法是典型的單源最短路徑演算法,用於計算乙個節點到其他所有節點的最短路徑。主要特點是以起始點為中心向外層層擴充套件,直到擴充套件到終點為止。dijkstra 演算法是很有代表性的最短路徑演算法,在很多專業課程中都作為基本內容有詳細...