问题描述
  想象你是一个在Warsaw的游客,而且预订了一次乘车旅行,去城镇外看一些令人惊异的景点。这辆公共汽车首先围绕城镇行驶一段时间(一段很长的时间,由于Warsaw是一个大城市),把在各自旅馆的人们带上。接着它就去了那个令人惊异的景点,几个小时后又回到城市中,再一次行驶到每一个旅馆,这一次把乘客放下。
  由于某种原因,每当你这样做的时候,你的旅馆总是第一个要上车的,而且是最后一个才下车的,意味着你不得不忍受两段经过所有当地旅馆的不那么愉快的旅行。这很明显不是你想要做的事(除非由于某种原因你真的要进入那些旅馆),所以让我们来做个改变。我们将开发一些软件使得那些观光公司能够把它们的乘车旅行路线安排得更公平——尽管这有时候可能会导致每一个人的总距离更长,但公平就是公平,不是吗?
  对于这个问题,有一个起始位置(观光公司的总部),h个需要接送游客的旅馆和一个目的地位置(令人惊异的景点)。我们需要找到一条路径,从总部出发,经过所有的旅馆,到景点去,再回来再一次经过所有的旅馆(可能按照不同的顺序),最后返回总部。为了保证没有一个游客(特别是你)被迫忍受两个完整的旅馆旅行,我们要求在去景点的路上接游客的前个旅馆,在回来的路上也得是前个让游客下车的。受制于这些限制条件,我们想让整个公车旅行尽可能短。注意这些限制条件可能会迫使公共汽车经过某个旅馆但是不停下来(这不算做让游客下车),后来再来这里让游客下车,样例就说明了这种情况。
输入格式
  第一行包含两个整数n和m满足3≤n≤20,2≤m,n是位置的总数(旅馆,总部和景点),m是汽车能在两个位置之间行驶的路径条数。
  n个不同的位置被标号为0到n-1,0是总部,1到n-2是旅馆,而n-1是景点。假定任意一对位置之间最多只有一条直接路径,而且从任意一个位置都能到达任意另一个位置(并不一定直接到达)。
  接下来m行,每行包含三个整数u,v和t,满足0≤u,v≤n-1,u≠v,1≤t≤3600,表示公共汽车可以在t秒的时间内直接在u和v之间到达(两个方向都可以)。
输出格式
  一个整数,表示可能的最短路线的总耗时。
样例输入
5 4
0 1 10
1 2 20
2 3 30
3 4 40
样例输出
300
数据规模和约定
  对于20%的数据:n=3
  对于50%的数据:3≤n≤10
  对于100%的数据:3≤n≤20,2≤m
好久不刷题了,帮朋友做的,状压DP+最短路,算了一下复杂度超了。再想起来在写吧。
思路:先floyd处理出来两点之间的最短路 O(n^3) ,然后状压dp[v | (1 << j)][j] = min (dp[v | (1 << j)][j], dp[v][i] + dis[i][j]),枚举状态和两个点。复杂度O(n*n*(1 << (n + 1)) 算了一下虽然10S,但是有点超。
/*************************************************************************
> File Name: ALGO-176.cpp
> Author: LyuCheng
> Created Time: 2018-02-07 00:10
> Description: 问题可拆分成:
先处理出来从0访问前h / 2个点 以第i个点为结尾的最短路,然后在枚举
n - 2个点作为起点,访问后h / 2以 n - 1作为终点的最短路,然后这就
是去景点的最短路,然后同理求从景点到起点的最短路
状态转移方程:dp[v | (1 << j)][j] = min (dp[v | (1 << j)][j], dp[v][i] + dis[i][j])
************************************************************************/ #include <iostream>
#include <string>
#include <vector>
#include <string.h> #define MAXN 21
#define INF 0x3f3f3f3f using namespace std; int n, m;
int u,v,w;
int mapn[MAXN][MAXN];
int dis[MAXN][MAXN];
int dp[( << MAXN)][MAXN]; //dp[i][j] 表示I状态(访问城市的状态)下最后访问j点的最短路的权值
int fdis[MAXN];//经过前h / 2个点的最短路
int edis[MAXN];//经过剩余点的最短路
vector <int> fir;
vector <int> sec;
int fres;
int sres; void floyd() {
memcpy(dis, mapn, sizeof mapn);
for (int i = ; i < n; ++ i) {
for (int j = ; j < n; ++ j) {
for (int k = ; k < n; ++ k) {
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
}
}
}
} void addedge(int u, int v, int w) {
if (mapn[u][v] > w) {
mapn[u][v] = w;
mapn[v][u] = w;
}
} void frist_half(int s) { //访问前 h / 2 点的最短路
memset(dp, INF, sizeof dp);
dp[][s] = ;
for (int v = ; v < ( << (n + )); ++ v) {
for (int i = ; i < n; ++ i) {
for (int j = ; j < n; ++ j) {
dp[v | ( << j)][j] = min (dp[v | ( << j)][j], dp[v][i] + dis[i][j]);
}
}
}
} int end_half(int s, int t) { //访问剩余的点的最短路
memset(dp, INF, sizeof dp);
dp[][s] = ;
for (int v = ; v < ( << (n + )); ++ v) {
for (int i = ; i < n; ++ i) {
for (int j = ; j < n; ++ j) {
dp[v | ( << j)][j] = min (dp[v | ( << j)][j], dp[v][i] + dis[i][j]);
}
}
}
int ans = INF;
for (int i = ; i < (int) sec.size(); ++ i) {
ans = min (ans, dp[sec[i]][t]);
}
return ans;
} void init() {
fres = INF;
sres = INF;
memset(mapn, , sizeof mapn);
for (int i = ; i < MAXN; ++ i)
for (int j = ; j < MAXN; ++ j)
mapn[i][j] = (i == j) ? : INF;
fir.clear();
sec.clear();
for (int i = ; i < ( << (n + )); ++ i) {
int s = ;
for (int j = ; j < n / ; ++ j)
if ((i & ( << j)) == )
s = ;
if (s == )
fir.push_back(i);
s = ;
for (int j = n / ; j < n - ; ++ j)
if ((i & ( << j)) == )
s = ;
if (s == )
sec.push_back(i);
}
} int main() {
// freopen ("in.txt", "r", stdin);
scanf ("%d %d", &n, &m);
init();
for (int i = ; i < m; ++ i) {
scanf ("%d %d %d", &u, &v, &w);
addedge(u, v, w);
}
floyd(); // floyd处理出来两点间的最短路 frist_half();
memset(fdis, INF, sizeof fdis);
for (int i = ; i < n; ++ i)
for (int j = ; j < (int) fir.size(); ++ j)
fdis[i] = min (fdis[i], dp[fir[j]][i]);
for (int i = ; i < n; ++ i)
fres = min(fres, fdis[i] + end_half(i, n - )); /*----------------------前半段处理完毕------------------------*/ frist_half(n - );
memset(edis, INF, sizeof edis);
for (int i = ; i < n; ++ i)
for (int j = ; j < (int) fir.size(); ++ j)
edis[i] = min (edis[i], dp[fir[j]][i]);
for (int i = ; i < n; ++ i) {
int res = end_half(i, );
sres = min(sres, edis[i] + res);
} printf ("%d\n", fres + sres);
return ;
}

算法训练 Bus Tour的更多相关文章

  1. 蓝桥杯 算法训练 Torry的困惑(基本型)(水题,筛法求素数)

    算法训练 Torry的困惑(基本型) 时间限制:1.0s   内存限制:512.0MB      问题描述 Torry从小喜爱数学.一天,老师告诉他,像2.3.5.7……这样的数叫做质数.Torry突 ...

  2. 蓝桥杯 算法训练 区间k大数查询(水题)

    算法训练 区间k大数查询 时间限制:1.0s   内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. ...

  3. 算法训练 Hankson的趣味题

    算法训练 Hankson的趣味题   时间限制:1.0s   内存限制:64.0MB        问题描述 Hanks 博士是BT (Bio-Tech,生物技术) 领域的知名专家,他的儿子名叫Han ...

  4. 算法训练 A+B Problem

     算法训练 A+B Problem   时间限制:1.0s   内存限制:512.0MB      问题描述 输入A,B. 输出A+B. 输入格式 输入包含两个整数A,B,用一个空格分隔. 输出格式 ...

  5. 算法训练 Hanoi问题

      算法训练 Hanoi问题   时间限制:1.0s   内存限制:512.0MB      问题描述 如果将课本上的Hanoi塔问题稍做修改:仍然是给定N只盘子,3根柱子,但是允许每次最多移动相邻的 ...

  6. 算法训练 区间k大数查询

    http://lx.lanqiao.org/problem.page?gpid=T11 算法训练 区间k大数查询   时间限制:1.0s   内存限制:256.0MB        问题描述 给定一个 ...

  7. 算法训练 Torry的困惑(基本型)

    http://lx.lanqiao.org/problem.page?gpid=T129 算法训练 Torry的困惑(基本型)   时间限制:1.0s   内存限制:512.0MB      问题描述 ...

  8. 算法训练 Anagrams问题

    http://lx.lanqiao.org/problem.page?gpid=T223 算法训练 Anagrams问题   时间限制:1.0s   内存限制:512.0MB      问题描述 An ...

  9. 蓝桥杯--算法训练 区间k大数查询

                                                                                 算法训练 区间k大数查询   时间限制:1.0 ...

随机推荐

  1. unity3d 计时功能舒爽解决方案

    上次也写了一篇计时功能的博客 今天这篇文章和上次的文章实现思路不一样,结果一样 上篇文章地址:http://www.cnblogs.com/shenggege/p/4251123.html 思路决定一 ...

  2. Python3开启Http服务

    在CMD命令行输入D: 切换到D盘, 然后输入 python -m http.server 8000 开启HTTP服务: 在浏览器地址栏输入 http://localhost:8000/

  3. 第一阶段·Linux运维基础-第2章·Linux系统目录结构介绍

    01 变量与PS1 02 添加用户 03 关闭SELinux 04 关闭iptables 05 显示中文乱码排查过程 06 总结 07 目录结构课程内容 08 Linux目录结构特点 09 Linux ...

  4. Angular6项目搭建

    参照 草根专栏- ASP.NET Core + Ng6 实战:https://v.qq.com/x/page/b076702elvw.html 安装工具: Nodejs, npm     最新版, h ...

  5. 标注点(Labeled Point)

    标注点LabeledPoint是一种带有标签(Label/Response)的本地向量,它可以是稠密或者是稀疏的.在MLlib中,标注点在监督学习算法中被使用.由于标签是用双精度浮点型来存储的,故标注 ...

  6. [CH0304]IncDec Sequence

    和NOIP2018DAY1T1类似的题目,但思维难度高多了. 这题既可以抬高路面,也可以降低路面,而且目标平面不确定,就难起来了. 但是两道题的基本思路几乎一样,同样我们将 2~n 的高度差分,1之所 ...

  7. Wordcount -- MapReduce example -- Mapper

    Mapper maps input key/value pairs into intermediate key/value pairs. E.g. Input: (docID, doc) Output ...

  8. 从电梯问题,看c和c++之间的区别(有点懂了)错觉错觉

    磕磕碰碰的也相继用c和c++构造了不少的电梯了.虽然对自我的表现不满意,但是总体来说还是有一定的收获的,对于c和c++之间的区别感觉也摸到了一点点门道了... 用c语言构造电梯的步骤: 第一步: 分析 ...

  9. jquery delayLoading.js插件的延迟加载效果和图片延迟加载

    1.首页给大家介绍一下这款插件的主要用途 主要应用于图片的延迟加载,而且可以变换不同的延迟加载效果,适合相册图片.有做相册的可以考虑应用. 2.兼容IE7以上都兼容,其他的浏览器也兼容.所以说兼容性还 ...

  10. 原生js移动端字体自适应方案

    自从进入新公司之后,就一直采用800的方案,也就是判断屏幕尺寸,大于800px是一种html字体处理方案,另一种方案是小于800px的html字体处理方案, 代码如下: (function(doc, ...