2016華為挑戰賽 尋路 賽題分析

2021-07-11 03:55:51 字數 2152 閱讀 3605

題意:在有向圖中,給定起點和終點,求經過所有必經點集合的最短路徑。(圖中所有的點最多只能經過一次)

限制:點數 <= 600, 必經點數 <= 50, 每個結點的最大出度為8

這是乙個np問題,是哈密頓迴路和tsp問題的變種。

分析:對於這個問題最直接的想法就是採用深度優先暴力搜尋,暴力搜尋演算法的時間複雜度太大(2^n),只能解決30點之內的初級用例。

而對於點數較多的測試用例,嘗試過下面幾種方法,雖然最後的實現效果不是很理想,官方的case 14,15沒有跑出來,因為設計的演算法都是基於貪心的,所以就掉溝裡了=_=

1. 插點法(基於floyd演算法)

idea:利用floyd演算法求出起點到終點的最短路,然後在最短路中依次加入必經點集合。

step1: 利用floyd演算法求出所有節點之間的最短路,並利用path陣列記錄下最短路徑。使用passpoint 陣列記錄已經經過的必經點(按起點到終點依次經過的順序排列)。

step2: 插入乙個必經點point。在已有的起點到終點的最短路上,選擇point需要插入到路徑中哪兩個相鄰的必經點之間,利用最小距離增量來選擇插入位置。對於相鄰點

passpoint[i]與passpoint[i+1], 利用floyd算出的最短路得到 bias = distance(passpoint[i], point) + distance(point,passpoint[i+1]) - distance(passpoint[i], passpoint[i+1]),需要驗證

distance(passpoint[i], point)與

distance(point,passpoint[i+1])中經過的結點是否已經被訪問,如果存在被訪問過的結點,則捨棄這個插入位置,遍歷後求得bias最小的位置,進行插入。如果對於每乙個插入的位置,都存在路徑

distance(passpoint[i], point)與distance(point,passpoint[i+1])中有訪問過的結點,則選擇衝突結點最小的那個位置,利用深度優先搜尋求passpoint[i] 經過點point到達passpoint[i+1]的最短路徑。重複step2,直到必經點集插入完全。

備註:在插入乙個必經結點時,引入的新路徑中可能包含必經點,此時應該把這些必經結點按順序加入到passpoint陣列中。

2. 依次連線路徑邊(基於dijkstra演算法)

idea: 依次選擇必經點中出度或入度最小的點,連線此點與其最近的必經點。

改進dijkstra演算法來記錄必經點point的直接後繼必經點序列(直接後繼的意思是point能夠在不經過其他必經點的情況下到達此必經點),同時也記錄必經點point的直接前驅必經點序列。選擇min(直接後繼數量, 出度,直接前驅數量,入度)最小的點,利用dijkstra演算法連線此點與其最近的必經節點。依次選擇連線路徑,直到完成起點到終點,經過所有必經點的路徑。

備註:此演算法適用於邊比較少的有向圖,實現時為了避免起點到終點的路徑未加入所有必經節點,而引入了禁忌邊tabu,來標誌兩個點之間可否連線。

3. 基於條件點的深度優先暴力搜尋(基於dijkstra演算法)

idea: 改進dijkstra演算法來記錄必經點point的直接後繼必經點序列(

直接後繼的意思是point能夠在不經過其他必經點的情況下到達此必經點

)。從起點開始暴力搜尋其直接後繼必經點,每搜尋到乙個點,利用dijkstra求兩個必經點之間最短距離,在搜尋過程中採用一些方法進行剪枝,例如剩餘必經點與終點的可達性。

備註:引入markpoint陣列,來記錄每個點隸屬的必經點。隸屬的標準如下:

①如果乙個必經點的出度或入度為1,那麼這個點的直接前驅或直接後繼結點就隸屬於此結點。

②如果乙個必經點的直接後繼必經點或直接前驅必經點只有乙個,那麼這個必經點到直接後繼點的最短路上的所有點都隸屬於這兩個結點。

可以利用點的隸屬屬性,避免dijkstra尋路時占用屬於其他必經點的重要結點。

總的來說,這種方法如果沒有採用有效的剪枝方式,很容易超時。

總結:對以上3種方法進行編碼實現,得到第一種方法的效果是最好的,儘管在很多情況下找到的都不是最優解。雖然最後沒能進入決賽,不過在這個過程中學到了很多圖論有關的演算法,也算是從小白到大白的一小步吧。

華為2023年精英挑戰賽總結

4月11日晚上23 59分就是32強出現的時刻,由於自己對自己的要求不高,以及自己的水平和時間有限,離結束時間還有很久就放棄了對演算法的優化,就導致了現在的結果。最後提交的結果如下 在3月4號看到今天華為精英挑戰賽的題目開始,自己覺得這個題目不難,加上有兩個同學邀請我參加此次比賽,因此自己也就參加了...

華為軟體精英挑戰賽總結

我們的成員分工 1 負責除錯 糾錯和上傳 2 負責查詢演算法思路 3 負責查詢演算法並且寫 框架 步驟 1 通過各個同學的專長進行分工,如上所示,確定一有思路就開小組會議討論。2 3號同學在網上查詢到乙個最基本的直連程式,該程式有錯誤,需要修改。3 1號同學同過3號同學給的直連 進行除錯和改錯,與此...

華為軟體精英挑戰賽總結

賽題連線 總體來看,是乙個np hard問題。我們隊的解題思路是 1 隨機選取伺服器的位置,用遺傳演算法尋優,那麼遺傳演算法中的判斷運算元就是第二步 2 在伺服器位置固定的情況下,利用最小費用最大流演算法計算總費用。該演算法思路詳見 其中求帶負權有向圖最短路,用到了fpga演算法,其實就是b ell...