旅行商问题:
N个点(N<16)的带权有向图D,求一条路径,使得这条路经过每个点恰好一次,
并且路径上边的权值和最小(或者最大),或者求一条具有这样性质的回路。
状态压缩:
将二进制表示十进制数N的点集,比如:
10 = 0000000000001010 代表第1和3个点已经路过18 = 0000000000010010 代表第1和4个点已经路过
一个整数就是一个点集,
dp_arr[binary][to_]代表经过点集 binary 中,当前终点为to_,
且路径最短的值,若该状态不存在就是INF
状态转移:
单点集合:状态存在dp_arr[1<<to_][to_] = 0;否则无穷大.
非单点集合:
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<<n ) – 1][to_] ) ( 0 <= to_ < N )
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
state_list.append( State( binary, end ) )
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_]
state_list.append( next_state )
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