旅行商問題:
n個點(n<16)的帶權有向圖d,求一條路徑,使得這條路經過每乙個點恰好一次。
而且路徑上邊的權值和最小(或者最大),
或者求一條具有這樣性質的迴路。
狀態壓縮:
將二進位制表示十進位制數n的點集,
比方:
10 = 0000000000001010 代表第1和3個點已經路過
18 = 0000000000010010 代表第1和4個點已經路過
乙個整數就是乙個點集。
dp_arr[binary][to_]代表經過點集 binary 中,當前終點為to_,
且路徑最短的值。若該狀態不存在就是inf
狀態轉移:
單點集合:狀態存在dp_arr[1<
非單點集合:
dp_arr[binary][to] = min( dp_arr[from_bin][from_] + graph[from_][to] )
from_為 from_ 與 to 右邊相連,且dp_arr[from_bin][from_] 狀態存在,
且 dp_arr[from_bin][from_] 中的 from_bin 尚未包括 to 點資訊的一系列點。狀態不存在就為inf
最後結果:
min( dp_arr[( 1<
python:
inf = 1 << 10
graph = [
[0, 2, inf, 3],
[inf, 0, 6, 1],
[inf, 2, 0, 4],
[5, 1, 3, 0]
]state_list =
citys = 4
dp_arr = [ [ inf for i in xrange( citys ) ] for j in xrange( 1 << citys ) ]
class state:
def __init__( self, binary = none, end = none ):
self.binary = binary
self.end = end
def dp():
for to_ in range( citys ):
binary = 1 << to_
end = to_
dp_arr[binary][end] = 0
while len( state_list ):
pre = state_list.pop()
from_bin = pre.binary
from_ = pre.end
for to_ in xrange( citys ):
binary = 1 << to_
if binary & from_bin or graph[from_][to_] is inf:
continue
binary |= from_bin
next_state = state( binary, to_ )
distance = dp_arr[from_bin][from_] + graph[from_][to_]
dp_arr[binary][to_] = min( dp_arr[binary][to_], distance )
if __name__ == '__main__':
dp()
ans = min( [ dp_arr[( 1 << citys ) - 1][to_] for to_ in xrange( citys ) ] )
print ans
旅行商問題 狀態壓縮
二進位制的很多應用離不開集合這個概念,我們都知道在計算機當中,所有資料都是以二進位制的形式儲存的。一般乙個int整形是4個位元組,也就是32位bit,我們通過這32位bit上0和1的組合可以表示多大21億個不同的數。如果我們把這32位bit看成是乙個集合,那麼每乙個數都應該對應集合的一種狀態,並且每...
狀態壓縮DP 旅行商問題
題目描述 給定乙個n個頂點組成的帶權有向圖的距離矩陣d i j inf表示沒有邊 要求從頂點0出發,經過每個頂點恰好一次後再回到頂點0.問所經過的邊的總權重的最小值是多少?限制條件 題目解析 這個問題就是著名的旅行商問題 tsp 所有可能的路線有 n 1 種。這是乙個非常大的值,即使題中n已經很小了...
從旅行商問題談狀態壓縮DP
乙個商品推銷員要去若干個城市推銷商品,該推銷員從乙個城市出發,需要經過所有城市後,回到出發地。應如何選擇行進路線,以使總的行程最短?請輸出最短行程。節點個數 n 滿足 2 leq n leq 20 路的長度小於 1000 例如這個旅行商問題,可能的路線一共有 n 1 種,如果純暴力試遍每一種方案,那...