洛谷P1171 售货员的难题 Tsp问题
洛谷P1171 售货员的难题
状压DP
1 #include <cstdio> 2 #define For(i,j,k) for(int i=j;i<=k;i++) 3 #define min(a,b) ((a) < (b) ? (a) : (b)) 4 using namespace std ; 5 6 const int N = 21,inf = 1e8 ; 7 int n,mi,all ; 8 int dis[N][N]; 9 int dp[N][1<<20] ; 10 int bin[22] ; 11 12 inline int read() 13 { 14 int x = 0 , f = 1 ; 15 char ch = getchar() ; 16 while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 17 while(ch>='0'&&ch<='9') { x = x * 10+ch-48 ; ch = getchar() ; } 18 return x * f ; 19 } 20 21 int main() 22 { 23 n = read() ; 24 bin[1] = 1 ; 25 For(i,2,21) bin[ i ] = bin[ i-1 ] * 2 ; 26 all = (1<<n)-1 ; 27 For(i,1,n) 28 For(j,1,n) dis[ i ][ j ] = read() ; 29 For(i,0,n) 30 for(int j=1;j<=all;j+=2) dp[ i ][ j ] = inf ; 31 dp[1][1] = 0 ; 32 for(int zt=3;zt<=all;zt+=2) 33 For(i,2,n) { 34 if(!(zt&bin[i])) continue ; 35 For(j,1,n) 36 if(zt&bin[j]) dp[i][zt] = min(dp[i][zt],dp[j][zt-bin[i]]+dis[j][i]) ; 37 } 38 mi = inf ; 39 For(i,2,n) 40 if( dp[i][all]+dis[i][1] < mi ) mi = dp[i][all]+dis[i][1] ; 41 printf("%d\n",mi) ; 42 return 0 ; 43 }
搜索
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 using namespace std; 5 int n,min1=200010,sum,minv[21],mind=200010; 6 bool vis[21]; 7 struct node{ 8 int dis,id; 9 }a[21][21],b[21]; 10 void dfs(int q,int last){ 11 if(q==n){ 12 min1=min(min1,sum+minv[last]); 13 return ; 14 } 15 for(int i=2;i<=n;i++) 16 if(!vis[a[last][i].id]){ 17 if(sum+a[last][i].dis>min1)return;//如果当前已走的距离已经大于当前最优值 返回 18 if(sum+a[last][i].dis+n-q+mind>=min1)return ; 19 //假想最小值剩下的村庄(n-q)的距离都是1 并且最后回到1的时候的距离也是最小的。 20 //如果此时还是超了当前最小值 后面的就都不需要搜了。 21 vis[a[last][i].id]=1; 22 sum+=a[last][i].dis; 23 dfs(q+1,a[last][i].id); 24 vis[a[last][i].id]=0; 25 sum-=a[last][i].dis; 26 } 27 } 28 bool cmp(node a,node b){ 29 return a.dis<b.dis; 30 } 31 int main(){ 32 cin>>n; 33 for(int i=1;i<=n;i++){ 34 for(int j=1;j<=n;j++){ 35 cin>>a[i][j].dis; 36 a[i][j].id=j; 37 } 38 minv[i]=a[i][1].dis;//minv[i]表示i村庄到1的距离 39 if(i!=1)mind=min(mind,minv[i]);//表示所有村庄到1的最短距离(不包括1到1) 40 sort(a[i]+1,a[i]+n+1,cmp);//读数据时每次得到一行的值后对边值排序。这样可以更快得到较优值。 41 } 42 vis[1]=1; 43 dfs(1,1); 44 cout<<min1; 45 return 0; 46 }