题目链接:

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个国家,编号从11到nn,各个国家之间通过mm条双向航线连接,第ii条航线连接第u_iu​i​​个国家与第v_iv​i​​个国家,通过这条航线需要消耗w_iw​i​​升油,且从11号国家可以直接或间接到达22到nn中任意一个国家。Victor一开始位于11号国家,他想知道从11号国家出发,经过各个国家至少一次并最后回到11号国家消耗的总油量的最小值是多少。
输入描述
第一行包含一个整数TT,表示测试数据的组数。每组测试数据的第一行有两个整数nn和mm,表示国家的个数和航线的条数。接下来mm行,每行三个整数u_iu​i​​, v_iv​i​​, w_iw​i​​,描述一条航线。1\leq T\leq 201≤T≤20。1\leq n\leq 161≤n≤16。1\leq m\leq 1000001≤m≤100000。1\leq w_i\leq 1001≤w​i​​≤100。1\leq u_i, v_i \leq n1≤u​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

方法二:先floyd,再直接上普通tsp的做法

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 const int maxn = 33;
 7
 8 int mat[maxn][maxn];
 9 int dp[(1 << 16)+10][maxn];
10
11 int n, m;
12
13 void floyd() {
14     for (int k = 0; k < n; k++) {
15         for (int i = 0; i < n; i++) {
16             for (int j = 0; j < n; j++) {
17                 mat[i][j] = min(mat[i][j], mat[i][k] + mat[k][j]);
18             }
19         }
20     }
21 }
22
23 void init() {
24     memset(mat, 0x3f, sizeof(mat));
25     for (int i = 0; i < maxn; i++) mat[i][i] = 0;
26     memset(dp, 0x3f, sizeof(dp));
27 }
28
29 int main() {
30     int tc;
31     scanf("%d", &tc);
32     while (tc--) {
33         init();
34         scanf("%d%d", &n, &m);
35         int u, v, w;
36         while (m--) {
37             scanf("%d%d%d", &u, &v, &w);
38             u--; v--;
39             if (mat[u][v] > w) mat[u][v] = mat[v][u] = w;
40         }
41         floyd();
42         dp[1][0] = 0;
43         //这里只是做出一个哈密顿通路
44         for (int s = 1; s < (1 << n); s++) {
45             for (int i = 0; i < n; i++) {
46                 if (s&(1 << i)) {
47                     for (int j = 0; j < n; j++) {
48                         if ((s&(1 << j))== 0) {
49                             dp[s | (1 << j)][j] = min(dp[s | (1 << j)][j], dp[s][i] + mat[i][j]);
50                         }
51                     }
52                 }
53             }
54         }
55         //补回路
56         int ans = 0x3f3f3f3f;
57         for (int i = 1; i < n; i++) {
58             ans = min(ans, dp[(1 << n) - 1][i] + mat[i][0]);
59         }
60         if (n == 1) printf("0\n");
61         else printf("%d\n", ans);
62     }
63     return 0;
64 }

View Code

转载于:https://www.cnblogs.com/fenice/p/5293657.html

HDU 5418 Victor and World 允许多次经过的TSP相关推荐

  1. hdu 5418 Victor and World (floyd+状压dp)

    题目大意:可重复访问顶点的TSP问题. 解法:点击打开链接 坑点:n=1 #include<iostream> #include<cstdio> #include<cst ...

  2. 【HDU - 5418】Victor and World(tsp旅行商问题,状压dp,floyd最短路,图论)

    题干: After trying hard for many years, Victor has finally received a pilot license. To have a celebra ...

  3. hdu 5420 Victor and Proposition 线段树建图+强连通分量

    题意: http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=620&pid=1003 题目求有多少对互为充要 ...

  4. hdu 5418(状态压缩dp+Floyd)

    点击打开链接 解题思路:这道题目和TSP问题很相似,唯一不同的是同一个点可以重复走几次.... 这道题目只有16个顶点,所以很容易想到状态压缩dp,dp[i][j]表示到达顶点i时的状态为j的最小花费 ...

  5. 最短哈密顿环 退火_hdu 5418 Victor and World (最短哈密顿回路)

    给你n个国家,m条路线:u_i与v_i之间的距离w_i. 输出从1号国家出发经过每个国家至少一次再回到1号国家的最短距离. [官方题解]: 我们首先需要预处理出任意两个国家之间的最短距离,因为数据范围 ...

  6. hdu 5420 Victor and Proposition(强连通+线段树建图)

    题意:给出一棵树,每个点都给一个x,d,代表它和x这个点以及以下深度差小于d的点都有一条有向边,求互相可达的u,v对数. 做法:可以很容易发觉如果我们把点连好然后直接找强连通分量,然后答案就是每个强连 ...

  7. linux系统起来时间,linux 系统时间调整

    BZOJ 3083: 遥远的国度 [树链剖分 DFS序 LCA] 3083: 遥远的国度 Time Limit: 10 Sec  Memory Limit: 1280 MBSubmit: 3127   ...

  8. linux中自动启动不了怎么办,linux:/etc/rc.local 不能自动启动问题

    前段时间安装LNMP环境,配置/etc/rc.local的时候配置了启动mysql.nginx.php以及关闭防火墙,可结果重启了七八次还是自启动不了后来终于找到原因了 看下图: /etc/rc.lo ...

  9. Victor and World(spfa+状态压缩dp)

    题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 Victor and World Time Limit: 4000/2000 MS (Java/ ...

最新文章

  1. Android应用开发—TextView的动态创建
  2. [UOJ422]小Z的礼物
  3. JBoss Eclipse IDE
  4. 1874 素数和最大 - Wikioi
  5. mysql 异常关机后 无法查数据_MySQL数据库非法关机造成数据表损坏怎么排查 | 学步园...
  6. Hadoop之NameNode和SecondaryNameNode工作机制详解
  7. c++ mqtt客户端_MQTT详解及百度物接入连接手机测试(含源码) 秦子帅
  8. 接口文档下的渗透测试(Swagger)
  9. 基于MVC4+EasyUI的Web开发框架经验总结(6)--在页面中应用下拉列表的处理
  10. 灵活应对算法大赛新挑战,极清晰比赛思路你值得拥有
  11. setpairint,int 的用法
  12. Leetcode201. Bitwise AND of Numbers Range数字范围按位与
  13. Coreldraw x6离线激活注册机免费下载安装教程
  14. BUUCTF pwn rootersctf_2019_xsh
  15. 关于MFi认证你所必须要知道的事情
  16. 【git 常用配置及常用命令】
  17. Webpack--模块热替换(HMR)
  18. swap未禁用导致的k8s NotReady
  19. TP-LINK TL-WR841N 路由变无线交换机设置
  20. 【经典面试题】strcmp 函数的实现

热门文章

  1. AltiumDesigner那些让你效率翻倍的技巧汇总 (持续更新)
  2. 2023合肥工业大学计算机考研信息汇总
  3. 论文笔记: Black Re-ID 黑衣人重识别
  4. 8个数,分成四组,每两个为一组,有多少种分法?
  5. mybatis 在语句中使用to_char时报错
  6. 用Python进行人脸识别「包括源代码」
  7. 中小河流水文监测系统
  8. 看完3d打印机类型及优缺点,再决定选哪款stratasys3D打印机
  9. esp32获取网络时间和天气
  10. 不存在万有集定理的证明