欧几里得旅行商问题是对平面上给定的n个点确定一条连接各点的最短闭合旅程的问题,下图a给出了7个点问题的解。这个问题的一般形式是NP完全的,故其解需要多于多项式的时间。

                 

(a)                                                          (b)

J.L.Bentley建议通过只考虑双调旅程来简化问题,这种旅程即为从最左点开始,严格地从左到右直至最右点,然后严格地从右到左直至出发点。b显示了同样7个点问题的最短双调路线。在这种情况下,多项式时间的算法是可能的。

描述一个确定最优双调路线的O(n^2)时间的算法,可以假设任何两点的x坐标都不相同。

将各个节点从左到右排序,编号为1,2,3,.....,n。对于任意的i和j(其中1<=i,j<=n)。

现在有两条路径A、B都是从点1出发,A走的路径为1~ i ,B走的路径为1~ j ,

即A、B有公共的起点,但途中没有交叉点(即终点之前不存在 i=j ),终点可能重合(i=j),也可能不重合(i≠j),这取决与我们要求的问题。

令s=max(i,j),则从1到s所有的点一定在路径A或者路径B上,不会有遗漏的点.

对于特定的 i 和 j ,路径A、B存在多种可能的走法,其中比有一种2条路径的和最小的走法,我们把这2条路径的和记为b[i,j];当i=j时,b[i,j]表示了从1到 i 的双调TSP的解;当i=j=n时 b[i,j] 就表示了整个问题的最终解法。

我们可以采用DP(动态规划)求解

上图表示对b[i,j]的递推情况,开始时,显然b[i,j]=0,而i=0或j=0也可以直接确定b[i,j]的值;

基于对称的考虑,表的左下半部和右上半部的数值将完全相同,所以在生成表的时候可以不用考虑下半部分

如何求递推?分一下几种情况

① i > j (即图的右上部分)

已知b[i,j] ,求b[i+1,j],只要将A直接延长到 i+1就行。

b[i+1,j] = b[i,j] + distance(i,i+1)

i = j (对角线部分)

假设已知b[i,i],求b[i+1,i],可以想象,此时AB两条路径在终点 i 相交,因为现在我们要求A的终点为i+1,所以不得不把相交的AB在i点拆开。

事情没那么简单,拆开后,我们需要在路径A找任意点u(0<=u<=i),使点u连接点i+1.

我们需要找到 min{ b[u,j] + distance(u, i+1)},即遍历 b[1..i, j],刚好这是图的左下部分,因为这个部分是和右上部分对称的,所以可以直接利用右上部分的数据。

b[i+1,j] = min{ B[u,i] + w(u,i+1) }

③ 确定b[n,n],即确定最终的解。

前面 ①②部分已经可以把所有的点都走一次了,现在我们最后需要做的是,把AB路径的头连接起来

那怎么连接才能让AB路径加起来最短呢?

前面我们说过: s=max(i,j),则从1到s所有的点一定在路径A或者路径B上,不会有遗漏的点

通过①②我们已经求出 1~s 点的所有数据。

也就是我们可以通过 min{ b[n,k] + distance(n,k)} 其中 1<=k<n 求出b[n,n];

b[n,n] =  min{ b[n,k] + distance(n,k)}

总结一下:

b[i,j] = b[i-1,j] + distance(i-1,i) (j+1 < i ,蓝色部分)

 b[i,j] = min{ B[u,i] + w(u,i+1) } (j+1 = i ,红色部分)

b[n,n] =  min{ b[n,k] + distance(n,k)}  0<=k<n

下面以2014百度之星Disk Schedule为例子,使用TSP算法

Problem Description

有很多从磁盘读取数据的需求,包括顺序读取、随机读取。为了提高效率,需要人为安排磁盘读取。然而,在现实中,这种做法很复杂。我们考虑一个相对简单的场景。
磁盘有许多轨道,每个轨道有许多扇区,用于存储数据。当我们想在特定扇区来读取数据时,磁头需要跳转到特定的轨道、具体扇区进行读取操作。为了简单,我们假设磁头可以在某个轨道顺时针或逆时针匀速旋转,旋转一周的时间是360个单位时间。磁头也可以随意移动到某个轨道进行读取,每跳转到一个相邻轨道的时间为400个单位时间,跳转前后磁头所在扇区位置不变。一次读取数据的时间为10个单位时间,读取前后磁头所在的扇区位置不变。磁头同时只能做一件事:跳转轨道,旋转或读取。
现在,需要在磁盘读取一组数据,假设每个轨道至多有一个读取请求,这个读取的扇区是轨道上分布在 0到359内的一个整数点扇区,即轨道的某个360等分点。磁头的起始点在0轨道0扇区,此时没有数据读取。在完成所有读取后,磁头需要回到0轨道0扇区的始点位置。请问完成给定的读取所需的最小时间。

Input

输入的第一行包含一个整数M(0<M<=100),表示测试数据的组数。
对于每组测试数据,第一行包含一个整数N(0<N<=1000),表示要读取的数据的数量。之后每行包含两个整数T和S(0<T<=1000,0<= S<360),表示每个数据的磁道和扇区,磁道是按升序排列,并且没有重复。

Output

对于每组测试数据,输出一个整数,表示完成全部读取所需的时间。

Sample Input

3

1

1 10

3

1 20

3 30

5 10

2

1 10

2 11

Sample Output

830

4090

1642

我们把要读取的数据的位置定义为 坐标(T,S),化成坐标后,我们需要对T的大小进行排序。

然后按照TSP的思路进行求解即刻。

#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
#define INF 88888888888
struct Data {int T, S;
};int b[1001][1001];
Data p[1001];
int N;int distance(Data x, Data y) {int dis;dis = abs(x.T - y.T) * 400;int tmp = abs(x.S - y.S);if (tmp > 180)dis += 360 - tmp;else dis += tmp;return dis;
}bool cmp(Data x, Data y) {return x.T < y.T;
}void DP() {int i, j, k;b[0][0] = 0;b[1][0] = distance(p[1], p[0]);for (i = 2; i <= N; i++) {for (j = 0; j < i; j++) {if (i != j + 1)b[i][j] = b[i - 1][j] + distance(p[i - 1], p[i]);else {b[i][j] = INF;int temp;for (k = 0; k < j; k++) {temp = b[i - 1][k] + distance(p[k], p[i]);if (temp < b[i][j])b[i][j] = temp;}}}}//求b[n][n]b[N][N] = INF;int temp;for (k = 0; k < N; k++) {temp = b[N][k] + distance(p[N], p[k]);if (temp < b[N][N])b[N][N] = temp;}
}int main() {int M;cin >> M;while (M--) {cin >> N;p[0].T = 0;p[0].S = 0;for (int i = 1; i <= N; i++) {cin >> p[i].T >> p[i].S;}sort(p, p + N + 1, cmp);DP();cout << b[N][N] + N * 10 << endl;}return 0;
}

双调TSP问题通俗讲解相关推荐

  1. 人工智能算法通俗讲解系列(二):逻辑回归

    2019独角兽企业重金招聘Python工程师标准>>> 今天,我们介绍的机器学习算法叫逻辑回归.它英语名称是Logistic Regression,简称LR. 跟之前一样,介绍这个算 ...

  2. Hadoop平台K-Means聚类算法分布式实现+MapReduce通俗讲解

        Hadoop平台K-Means聚类算法分布式实现+MapReduce通俗讲解 在Hadoop分布式环境下实现K-Means聚类算法的伪代码如下: 输入:参数0--存储样本数据的文本文件inpu ...

  3. 冲突域、广播域的通俗讲解

    冲突域.广播域的通俗讲解 1.冲突域(物理分段)         连接在同一导线上的所有工作站的集合,或者说是同一物理网段上所有节点的集合或以太网上竞争同一带宽的节点集合.这个域代表了冲突在其中发生并 ...

  4. 通俗讲解:图像傅里叶变换

    转自某乎:通俗讲解:图像傅里叶变换 - 知乎 这里我们主要要讲的是二维图像傅里叶变换,但是我们首先来看一张很厉害的一维傅里叶变换动图. 妈耶~厉害哇!它把时域和频域解释的很清楚! 什么!你看不懂! 简 ...

  5. 关于CSS浮动(float,clear)的通俗讲解(经验分享)

    很早以前就接触过CSS,但对于浮动始终非常迷惑,可能是自身理解能力差,也可能是没能遇到一篇通俗的教程. 前些天小菜终于搞懂了浮动的基本原理,迫不及待的分享给大家. 写在前面的话: 由于CSS内容比较多 ...

  6. 二维小波变换_小波变换完美通俗讲解系列之 (一)

    声明:该篇文章转自csdn,原始博主已经找不到了,在这里给出转载博主地址,如有侵权,请私信我删除. https://blog.csdn.net/liusandian/article/details/5 ...

  7. vue标准时间改为时间戳_区块链科普005:什么是时间戳?白话通俗讲解时间戳是什么意思?...

    原标题:区块链科普005:什么是时间戳?白话通俗讲解时间戳是什么意思? 八宝饭区块链:什么是时间戳 时间戳是什么?可能很多人都没有听过,但是作为办公一族应该掌握这个技能.时间戳技术就是数字签名技术一种 ...

  8. Java多数据源最通俗讲解

    Java多数据源最通俗讲解 before after 理论 实操 编码 小总结 before 项目中可能会用到很多的数据源,例如目前这个项目中用到了五个数据源,那么数据源的 配置和数据源的切换就成为了 ...

  9. 通俗讲解 依概率收敛,大数定理和中心极限定理

    通俗讲解 依概率收敛,大数定理和中心极限定理 依概率收敛 首先说一下结论,依概率收敛是一种基础证明工具,可以类比到高数中的极限定义,将一种直觉上的 "逼近某个数" 用数学公式来定义 ...

最新文章

  1. Android stadio
  2. XenDesktop7-基于SCVMM2012SP1的部署
  3. 【Paper】2015_Song_Consensus of Heterogeneous Agents with Linear Discrete Dynamics
  4. 事务操作 mysql的事务操作
  5. svn服务的安装与设置 .
  6. 奇安信代码卫士帮助微软修复多个高危漏洞,获官方致谢
  7. android 调用百度地图api
  8. 通过shell登录OSC并备份博文
  9. pythonlocust使用技巧_python locust 性能测试:HOOKS钩子方法
  10. aix oracle 创建实例,11gR2 for AIX使用dbca创建数据库遇到ORA-03113错误的案例
  11. 网站备案 ICP备案流程
  12. matlab欠采样,科学网—傅立叶欠采样算子的Matlab代码 - 屈小波的博文
  13. Win7系统上的appdata是什么文件夹可以删除roaming
  14. 前端 flex: 1; 到底是什么意思?
  15. 天人合一物我相融,站点升级渐进式Web应用PWA(Progressive Web Apps)实践
  16. 安装create-react-app教程及简单配置
  17. 史上最详细bitbucket入门手册,手把手操作指南
  18. 深度学习之图像隐写去除(DDSP模型 Steganography Removal)
  19. Python合并不同数量的Excel单元格
  20. 【JavaWEB】项目实战-黑马面面

热门文章

  1. 今晚开播 | 人脸识别的最新进展以及工业级大规模人脸识别实践探讨
  2. 奇点云发布三大无人零售终端产品,“云”“端”结合赋能零售商
  3. 领跑交互新时代 蓦然认知助力传统产业智能化升级
  4. Spring Boot 2.X整合Spring-cache,让你的网站速度飞起来
  5. PageHelper 在 Spring Boot + MyBatis 中合理且规范的使用方法
  6. 老弟,你连HTTPS 原理都不懂,还给我讲“中间人攻击”,逗我吗...
  7. 阿里算法,浙大博士带你写项目经历!
  8. 收藏!PyTorch常用代码段合集
  9. 剑指offer_第10题_矩形覆盖
  10. 大型AI已有自主意识了?LeCun开喷Open AI首席科学家