TSP问题(小规模)

问题
货郎担问题提法:有n个城市,用1,2,…,n表示,城i,j之间的距离为dij,有一个货郎从城1出发到其他城市一次且仅一次,最后回到城市1,怎样选择行走路线使总路程最短?

思路:
假设周游路线是开始于结点1并终止于结点1 的一条简单路径。每一条周游路线都由一条边〈1,k〉和一条由结点k 到结点1 的路径所组成, 其中k∈V-{1} ; 而这条由结点k 到结点1 的路径通过V-{1 ,k}的每个结点各一次。容易看出, 如果这条周游路线是最优的, 那么这条由k 到1 的路径必定是通过V-{1, k}中所有结点的由k到1的最短路径, 因此最优性原理成立。
设g(i,S)是由结点i开始, 通过S中的所有结点, 在结点1终止的一条最短路径长度。g(1,V-{1}) 是一条最优的周游路线长度。于是, 可以得出

g(1,V-{1}) = min{c1k + g( k,V-{1,k})} 2≤k≤ n
一般化可得g(i,S) = min{ cij+ g(j,S-{j}) }

#include 
#include 
#include 
using namespace std;
const int INF = 1<<20;
const int N = 16;
int G[N][N], vis[N] ,n, start = 0; 

// d(i,s):从 i 点出发,经过S集合中所有点一次最后到达start的最小代价。
int solve(int cur, int num){
	
	if(num == 1) return G[cur][start];
	
	int mincost = INF;
	for(int j = 0; j < n; ++j){
		if(!vis[j] && j != start){
			
			if(mincost <= G[cur][j]+G[j][start]) continue; // 提前淘汰一些不可能被选中的点 
			vis[j] = 1;
			mincost = min(mincost , G[cur][j] + solve(j,num-1));
			vis[j] = 0;
		}
	}
	
	return mincost;
}

int main()
{
	freopen("in.txt","r",stdin);
	while(scanf("%d",&n) == 1&&n){
		for(int i = 0; i < n; ++i){
			for(int j = 0; j < n; ++j){
				scanf("%d",&G[i][j]);
			}
		}
		 
		memset(vis,0,sizeof(vis));vis[start] = 1;
		int ans = solve(start, n);
		printf("%d\n",ans);
	}

	return 0;
}


你可能感兴趣的:(Practice,动态规划)