Travelling (compressed state, classic traveling salesman problem)

After coding so many days,Mr Acmer wants to have a good rest.So travelling is the best choice!He has decided to visit n cities(he insists on seeing all the cities!And he does not mind which city being his start station because superman can bring him to any city at first but only once.), and of course there are m roads here,following a fee as usual.But Mr Acmer gets bored so easily that he doesn't want to visit a city more than twice!And he is so mean that he wants to minimize the total fee!He is lazy you see.So he turns to you for help.

Input

There are several test cases,the first line is two intergers n(1<=n<=10) and m,which means he needs to visit n cities and there are m roads he can choose,then m lines follow,each line will include three intergers a,b and c(1<=a,b<=n),means there is a road between a and b and the cost is of course c.Input to the End Of File.

Output

Output the minimum fee that he should pay,or -1 if he can't find such a route.

 

Sample Input

2 1

1 2 100

3 2

1 2 40

2 3 50

3 3

1 2 3

1 3 4

2 3 10

Sample Output

100

90

7

 

Topic effect: a person go to the N city tour, he can start from any city, there are m road between the cities, the cost of each road takes to do, solved through all the cities, and each city visited not more than twice the minimum cost

Ideas: we have been to X number of cities, and the number of times that X number of cities are visited, and is currently in the city as a state, as a starting point to the current city went to other cities to try and update the status of the corresponding minimum cost but the number of these cities have been to this state to how to store it, open a n-dimensional array is clearly unrealistic, this time, we thought encoding compression can be applied to state:

In line with the number of questions asked of each city only three have not been visited, been there once, been there twice, so a ternary number can be stored status of a city, then, n bits Three number system can be stored state n cities, we assume that the ternary number X, for the city i bit i trit Therefore, the number of cities visited i is equal to X / (3 ^ i)% 3

Thus, we can conclude recursive formula:

Man for me: dp [i] [j] = min (dp [i] [j], dp [i-3 ^ j] [v] + w [v] [j]) 

One for All: dp [i + 3 ^ v] = min (dp [i + 3 ^ v] [v], dp [i] [j] + w [j] [v])

 

This problem has been encountered problem, forgetting the difference between memest and fill function, memset is assigned byte by byte, I started using INF = 999999, the results led to the error, so if a general assignment for 1 and 0

With code:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define INF 0x3f    
#define check(x,y) (x/tab[y])%3   //获取状态X中,到达Y城市的次数 
using namespace std;
int tab[11]= {1},dp[60000][11];  //tab数组存储#3的次方数 
int main() {
	int n,m;
	for(int i=1; i<=10; i++) {   //初始化tab数组 
		tab[i]=tab[i-1]*3;
	}
	while(cin>>n>>m) {
		int w[11][11],cost=0x3f3f3f3f;
		memset(w,INF,sizeof(w));
		memset(dp,INF,sizeof(dp));     //初始化为无穷大 
		int x,y,wi;
		for(int i=0; i<m; i++) {
			cin>>x>>y>>wi;
			x--;
			y--;     //城市编号转化成 0开始 
			w[x][y]=w[y][x]=min(w[x][y],wi);
		}
		for(int i=0; i<n; i++)dp[tab[i]][i]=0;  //初始化从每个城市出发的情况,保证每种状态都能遍历到 
		for(int i=1; i<tab[n]; i++) {
			bool flag=true;   //设置标志flag,如果 i 状态下,去过了 n个城市,则可以尝试更新最小花费 
			for(int j=0;j<n;j++){
				
				if(check(i,j)==0){  
					flag=false;  //i 状态下 j 城市没有去过 
					continue;
				}
				for(int v=0;v<n;v++){
					if(check(i,v)==2)continue;  //如果 i 状态下 v城市已经访问了两次跳过 v 城市 
					dp[i+tab[v]][v]=min(dp[i+tab[v]][v],dp[i][j]+w[j][v]);  //我为人人递推 
				}
			}
			if(flag){  //0~n-1城市都有去过 
				for(int j=0;j<n;j++){
					cost=min(cost,dp[i][j]);  //尝试更新最小花费 
				}
			}
		}
		if(cost==0x3f3f3f3f)cost=-1;  //如果不能完成遍历所有城市的目标 
        cout<<cost<<endl;
       // printf("%d\n",cost);
	}
	return 0;
}

 

Published 42 original articles · won praise 16 · views 3400

Guess you like

Origin blog.csdn.net/qq_41542638/article/details/102704149