POJ 3311 Hie with the Pie -- TSP 状态压缩dp

/*
	http://poj.org/problem?id=3311 Hie with the Pie
	旅行商问题,状态压缩的dp
*/
#include <cstdio>
#include <iostream>
#include <string>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
#define CLR(c,v) memset(c,v,sizeof(c))

template <typename _T>
_T Max(_T a, _T b){
	return (a>b)?(a):(b);
}
template <typename _T>
_T Max(_T a, _T b,_T c){
	return (a>Max(b,c))?(a):(Max(b,c));
}

const int inf  = -(1<<30);
const int INF  =  (1<<30);
const int M    =  12;

int d[M][M];
int dp[(1<<M)+M][M]; // dp[state][city] 在state状态下到达city的最优距离

void floyd(int n){ //求解任意两点间的最短距离
		for(int i = 0 ; i <= n ; i++)
			for(int j = 0 ; j <= n ; j++)
	for(int k = 0 ; k <= n ; k++) 
				if (d[i][j] > d[i][k] + d[k][j])
					d[i][j] = d[i][k] + d[k][j];
}

int main(){
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	int n;
	while(cin >> n,n){
		for(int i = 0; i <= n ; i++){
			for(int j = 0; j <= n ; j++){
				cin >> d[i][j]; // stand for distance[i->j]:d[i][j]
			}
		}
		floyd(n);
 		int bound = (1<<n) - 1;
		for(int state = 0; state <= bound ; state++){ // 
			for(int j = 0; j <= n ; j++){
				dp[state][j] = INF; // 因为我们要求最小值,所以初始最大
			}
		}
		
		for(int state = 1 ; state <= bound ; state++){
			for (int i = 1 ; i <= n ; i++){
				#define FROM (i-1)
				#define TO (j-1) // 这两意味着 从 FROM城市 到 TO城市
				if (!(state & 1<<FROM) )continue; // 如果该state状态不包括i城市
				if ( state == 1<<FROM ){ // 如果这个状态只涉及一个城市
					dp[state][i] = d[0][i]; // 那么最优路径一定为起点直接到这个点
				}else{
					for(int j = 1 ; j <= n ; j++){ // 否则枚举每一条线段 来维护dp[state][i]
						if ((state & 1<<TO) != 0 && i!=j)   // TO城市在state中 则不为0
						dp[state][i] = min(dp[state][i], dp[state ^ (1<<FROM)][j] + d[j][i]);
					}
				}
			}
		}
		int ans = INF;
		for(int i = 0 ; i <= n ; i++ )
			if(dp[bound][i] + d[i][0] < ans){
				ans = dp[bound][i] + d[i][0];
			}
		cout << ans << endl;
	}

	return 0;
}
#undef from
#undef to

你可能感兴趣的:(POJ 3311 Hie with the Pie -- TSP 状态压缩dp)