题目链接:

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来解这道题,就要做一点改变创新了。

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

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

代码:

 #include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int maxn=(<<)+;
static int INF; int dp[maxn][],cnt[maxn]; int mat[][]; int n,m; void get_cnt(){
memset(cnt,,sizeof(cnt));
for(int stat=;stat<(<<);stat++){
//统计每一个状态的已经访问了的节点的个数
for(int i=;i<;i++){
if(stat&(<<i)) cnt[stat]++;
}
}
} void init(){
memset(dp,0x3f,sizeof(dp));
INF=dp[][];
memset(mat,0x3f,sizeof(mat));
} int main(){
get_cnt();
int tc;
scanf("%d",&tc);
while(tc--){
init();
scanf("%d%d",&n,&m);
int u,v,w;
while(m--){
scanf("%d%d%d",&u,&v,&w);
u--; v--;
if(w<mat[u][v])
mat[u][v]=mat[v][u]=w;
}
dp[][]=;
for(int s=;s<(<<n);s++){
//做k次后能够保证引起后效性的那些转移也能得到最优解,有点像floyd算法的思想。
for(int k=;k<=cnt[s];k++){
for(int i=;i<n;i++){
//这里要做可行性减枝,否则时间会爆。
if(dp[s][i]!=INF){
for(int j=;j<n;j++){
dp[s|(<<j)][j]=min(dp[s|(<<j)][j],dp[s][i]+mat[i][j]);
}
}
}
}
}
printf("%d\n",dp[(<<n)-][]);
}
return ;
}

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

代码:

 #include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std; const int maxn = ; int mat[maxn][maxn];
int dp[( << )+][maxn]; int n, m; void floyd() {
for (int k = ; k < n; k++) {
for (int i = ; i < n; i++) {
for (int j = ; j < n; j++) {
mat[i][j] = min(mat[i][j], mat[i][k] + mat[k][j]);
}
}
}
} void init() {
memset(mat, 0x3f, sizeof(mat));
for (int i = ; i < maxn; i++) mat[i][i] = ;
memset(dp, 0x3f, sizeof(dp));
} int main() {
int tc;
scanf("%d", &tc);
while (tc--) {
init();
scanf("%d%d", &n, &m);
int u, v, w;
while (m--) {
scanf("%d%d%d", &u, &v, &w);
u--; v--;
if (mat[u][v] > w) mat[u][v] = mat[v][u] = w;
}
floyd();
dp[][] = ;
//这里只是做出一个哈密顿通路
for (int s = ; s < ( << n); s++) {
for (int i = ; i < n; i++) {
if (s&( << i)) {
for (int j = ; j < n; j++) {
if ((s&( << j))== ) {
dp[s | ( << j)][j] = min(dp[s | ( << j)][j], dp[s][i] + mat[i][j]);
}
}
}
}
}
//补回路
int ans = 0x3f3f3f3f;
for (int i = ; i < n; i++) {
ans = min(ans, dp[( << n) - ][i] + mat[i][]);
}
if (n == ) printf("0\n");
else printf("%d\n", ans);
}
return ;
}

HDU 5418 Victor and World 允许多次经过的TSP的更多相关文章

  1. ACM: HDU 5418 Victor and World - Floyd算法+dp状态压缩

    HDU 5418 Victor and World Time Limit:2000MS     Memory Limit:131072KB     64bit IO Format:%I64d & ...

  2. HDU 5418 Victor and World(状压DP+Floyed预处理)

    Victor and World Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Other ...

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

    [题目链接]:pid=5418">click here~~ [题目大意]: 问题描写叙述 经过多年的努力,Victor最终考到了飞行驾照. 为了庆祝这件事,他决定给自己买一架飞机然后环 ...

  4. HDU 5418 Victor and World (状态压缩dp)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5418 题目大意:有n个结点m条边(有边权)组成的一张连通图(n <16, m<100000 ...

  5. HDU 5418——Victor and World——————【状态压缩+floyd】

    Victor and World Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/131072 K (Java/Other ...

  6. HDU 5418 Victor and World (Floyd + 状态压缩DP)

    题目大意:从起点 1 开始走遍所有的点,回到起点 1 ,求出所走的最短长度. 思路:首先利用 Floyed 求出任意两点之间的最短距离 dis[i][j].求出任意两点之间的最短距离后,运用动态规划. ...

  7. HDU 5418 Victor and World (可重复走的TSP问题,状压dp)

    题意: 每个点都可以走多次的TSP问题:有n个点(n<=16),从点1出发,经过其他所有点至少1次,并回到原点1,使得路程最短. 思路: 给了很多重边,选最小的留下即可.任意点可能无法直接到达, ...

  8. HDU - 5067 / HDU - 5418 TSP

    集合表示多用[0,n)表示方法 HDU - 5067 经典TSP,每个顶点恰经过一次最优 #include<bits/stdc++.h> #define rep(i,j,k) for(in ...

  9. 【hdu 5418】 Victor and world

    [题目链接] 点击打开链接 [算法] 状压DP f[i][S]表示走的最后一步在i,状态为S 于是我们可以用最短路径 + 状压DP解决此题,由于不存在负边,所以可以用dijkstra+堆优化 [代码] ...

随机推荐

  1. Delphi XE10.1 引用计数

      以往的Delphi版本,不支持接口的Weak,和UnSafe的引用,支持对象的Weak, UnSafe,而且仅在Android和Ios平台上支持. 现在Delphi XE10.1 Berlin终于 ...

  2. window7下 cmd命令行 Mysql导出表结构 + 表数据

    命令格式 mysqldump -uroot -p 密码 库名 > 自定义路径/库名.sql

  3. 树莓派3B+学习笔记:5、安装vim

    以下操作使用root账户登陆. 1.在终端中输入 apt-get install vim 输入“y”,回车: 2.等一下,安装完成: 3.用vim新建一个文本文件测试一下,在终端重输入 vim tes ...

  4. stm32串口通信实验,一点笔记

    第一次深入学习stm32,花了好长时间才看懂代码(主要是C语言学习不够深入),又花了段时间自己敲了一遍,然后比对教程,了解了利用中断来串口通信的设置方法. 板子是探索版f407,本实验工程把正点原子库 ...

  5. python七类之集合

    集合 一.关键字 : set 定义是 s = {}    #当里面没有元素的时候​​表现为字典数据类型 s = {} #空的{}代表空的字典,而不是集合 print(type(s)) 集合是不可哈希的 ...

  6. 一个博客萌新的C语言之旅(持续更新中....)

    先更新上一次留下的的C语言练习答案,如下: #include <stdio.h> double mj(double r) { return 3.14*r*r; } int main() { ...

  7. ASP.NET Core 资源打包与压缩

    ASP.NET Core 资源打包与压缩 在ASP.NET 中可以使用打包与压缩来提高Web应用程序页面加载的性能. 打包是将多个文件(CSS,JS等资源文件)合并或打包到单个文件.文件合并可减少We ...

  8. 【洛谷P4556】 雨天的尾巴

    题面 题解 线段树合并 我们看到这道题目首先可以想到树上差分,然后\(dfs\)合并 发现题目让我们求的东西很好用线段树维护 于是可以想到线段树合并 全世界只有我写指针版动态开点线段树(大雾 如果你要 ...

  9. 【LG3242】 [HNOI2015]接水果

    题面 洛谷 题解 20pts 对于\(n,P,Q\leq 3000\),暴力判断每条路径的包含关系然后排序\(kth\)即可,复杂度\(O(PQ\log P)\) 另30pts 原树为一条链. 发现对 ...

  10. 同步备份工具之 rsync

    1.常用同步方法 SCP. NFS. SFTP. http. samba. rsync. drbd(基于文件系统同步,效率高) 2.rsync 介绍 rsync,英文全称是 remote synchr ...