哈密爾頓路徑屬於旅行商問題,是乙個np完全問題,即沒有乙個合適的演算法來解決它,只能用樸素演算法(也就是通常所說的暴力演算法)去進行優化。
但這類問題的時間複雜度是極其可怕的o(n!),當n比較小的時候,還可以通過暴力法解決,但當n=15的時候,15!=1307674368000;已經達到了萬億級別;你可以想象下就算以計算機的計算能力,也要跑多久才能解出答案;
所以np問題最常用的解法是近似解,即無解,尋找大概率出現的近似解;
hamilton路徑的定義:在一張圖中,從點0到點n-1不重不漏的恰好經過每乙個點一次的路徑。
但哈密爾頓路徑有乙個特點:當你計算了其中i條路徑的組合之後,計算i+1條的時候,是會重複計算前面已經計算過的值;
如何利用起來已經計算過的值,減少重複計算的步驟,這是乙個優化演算法的切入點;
因此狀態機資料結構出來了;
我們知道有n條路徑,那麼每條路徑都有兩種狀態:已經走過和沒走過;那分別用0|1來表示;
那麼當你處於某個路徑的終點的時候,並走過了i條路徑,你有多少種狀態呢,還是乙個階乘i!,但是你可以發現有個規律,這些階乘有共同重複的點;是不是可以用矩陣來表示呢,所以完整表示這些狀態不僅需要2n次方的狀態來表示路徑是否走過,還需要乙個二維深度去儲存這些路徑的組合狀態,索性,我們只需要最短路徑,但是怎麼去表示呢?
試想下前提條件:最短,所以我們處於某條路徑上,前面走過的路徑也肯定是那條路徑為終點的最短路徑;
目前我們已經走完了i條路徑,但我們並不知道處於哪條路徑的終點,那有多少情況呢,i種;
因為只有i條路徑已經走過了啊;那麼對於n條路徑
,那麼只需要n深度的矩陣就可以了;
所以我們需要乙個二維的深度去表示每條路徑;
那麼狀態機就是f[2次方][n];
那怎麼把這個矩陣給計算出來呢?
假設我們現在還是處於第i條路徑上,並且走過了前i條;所以用順序表示f的行為00001(i)11…111;
那麼有幾條路能夠走到i呢,肯定只有前面已經狀態為1的幾條;
而狀態機裡儲存的就是那條路徑當時的最短路徑,遍歷這幾條路徑就可以得出此時這個狀態下的最短路徑;
那麼i >> k & 1表示路徑已走過,且不是i的路徑;
for
(int k =
0; k < n;
++k)
}
當處於起點的時候,所有的路徑都還沒走過,所以第一行只有乙個值,就是最開始起點的路徑;
for
(let i =
1; i < i<}}
}
哈密爾頓道路與哈密爾頓迴路
簡介 1857年愛爾蘭數學家哈密爾頓發明了 周遊世界 玩具,用乙個正十二面體的20個頂點表示世界上20個大城市,30條稜代表這些城市之間的道路。要求遊戲者從任意乙個城市 即頂點 出發,延稜行走經過每個城市一次且只經過一次,最終返回出發地。哈密爾頓將此問題稱為周遊世界問題,並且作了肯定的回答。以下是一...
哈密爾頓環問題
哈密爾頓環 尤拉迴路是指不重複地走過所有路徑的迴路,而哈密爾頓環是指不重複地走過所有的點,並且最後還能回到起點的迴路。1 include2 include3 using namespace std 4int num 10001 求乙個點能過到達的邊的數量 5int map 1001 1001 6 i...
哈密爾頓環
尤拉迴路是指不重複的走過所有路徑的迴路,而哈密爾頓環是指不重複地走過所有的點,並且最後還能回到起點的迴路。使用簡單的深度優先搜尋,就能求出一張圖中所有的哈密爾頓環,下面給出一段參考程式 include include include include include include include u...