HDU 5418 Victor and World 允许多次经过的TSP

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 5418 Victor and World 允许多次经过的TSP相关的知识,希望对你有一定的参考价值。

题目链接:

hdu: 

  http://acm.hdu.edu.cn/showproblem.php?pid=5418

bestcoder(中文):

  http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=619&pid=1002

Victor and World

 
 Accepts: 99
 
 Submissions: 644
 Time Limit: 4000/2000 MS (Java/Others)
 
 Memory Limit: 262144/131072 K (Java/Others)
问题描述
经过多年的努力,Victor终于考到了飞行驾照。为了庆祝这件事,他决定给自己买一架飞机然后环游世界。他会驾驶一架飞机沿着规定的航线飞行。在地球上一共有nn个国家,编号从11nn,各个国家之间通过mm条双向航线连接,第ii条航线连接第u_iu?i??个国家与第v_iv?i??个国家,通过这条航线需要消耗w_iw?i??升油,且从11号国家可以直接或间接到达22nn中任意一个国家。

Victor一开始位于11号国家,他想知道从11号国家出发,经过各个国家至少一次并最后回到11号国家消耗的总油量的最小值是多少。
输入描述
第一行包含一个整数TT,表示测试数据的组数。

每组测试数据的第一行有两个整数nnmm,表示国家的个数和航线的条数。

接下来mm行,每行三个整数u_iu?i??, v_iv?i??, w_iw?i??,描述一条航线。

1\leq T\leq 201T201\leq n\leq 161n161\leq m\leq 1000001m1000001\leq w_i\leq 1001w?i??1001\leq u_i, v_i \leq n1u?i??,v?i??n
输出描述
每组测试数据输出一行一个整数,即消耗的总油量的最小值。
输入样例
1
3 2
1 2 2
1 3 3
输出样例
10

 

题解:

  这一道题与普通tsp的差别就在与状太转移变多了,设i,j为任意的两个点,s为压缩后的状态。dp[s][i]可以由dp[s][j]转移而来,这直接破坏普通TSP无后效性的前提。因此如果还想要用dp来解这道题,就要做一点改变创新了。

方法一:比较暴力的状态压缩

  这里状态转移用的是刷表法

代码:

技术分享
 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 
 7 const int maxn=(1<<16)+10;
 8 static int INF;
 9 
10 int dp[maxn][33],cnt[maxn];
11 
12 int mat[33][33];
13 
14 int n,m;
15 
16 void get_cnt(){
17     memset(cnt,0,sizeof(cnt));
18     for(int stat=0;stat<(1<<16);stat++){
19         //统计每一个状态的已经访问了的节点的个数
20         for(int i=0;i<16;i++){
21             if(stat&(1<<i)) cnt[stat]++;
22         }
23     }
24 }
25 
26 void init(){
27     memset(dp,0x3f,sizeof(dp));
28     INF=dp[0][0];
29     memset(mat,0x3f,sizeof(mat));
30 }
31 
32 int main(){
33     get_cnt();
34     int tc;
35     scanf("%d",&tc);
36     while(tc--){
37         init();
38         scanf("%d%d",&n,&m);
39         int u,v,w;
40         while(m--){
41             scanf("%d%d%d",&u,&v,&w);
42             u--; v--;
43             if(w<mat[u][v])
44                 mat[u][v]=mat[v][u]=w;
45         }
46         dp[1][0]=0;
47         for(int s=1;s<(1<<n);s++){
48             //做k次后能够保证引起后效性的那些转移也能得到最优解,有点像floyd算法的思想。 
49             for(int k=0;k<=cnt[s];k++){
50                 for(int i=0;i<n;i++){
51                     //这里要做可行性减枝,否则时间会爆。 
52                     if(dp[s][i]!=INF){
53                         for(int j=0;j<n;j++){
54                             dp[s|(1<<j)][j]=min(dp[s|(1<<j)][j],dp[s][i]+mat[i][j]);
55                         }
56                     }
57                 }
58             }
59         }
60         printf("%d\n",dp[(1<<n)-1][0]);
61     }
62     return 0;
63 }
View Code

 

以上是关于HDU 5418 Victor and World 允许多次经过的TSP的主要内容,如果未能解决你的问题,请参考以下文章

hdu 5418 Victor and World (状压dp)

BestCoder Round #52 (div.2) HDU 5418 Victor and World (DP+状态压缩)

HDOJ 5418 Victor and World 状压DP

HDU Victor and World (最短路+状态压缩)

HDU5421Victor and String(回文树)

HDU - 5421:Victor and String (回文树,支持首尾插入新字符)