状态压缩动态规划 -- 旅行商问题
旅行商问题:
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