货郎问题java_货郎问题
货郎问题(Traveling Salesman Problem,简称“TSP”)也叫货郎担问题,中国邮路问题,旅行商问题等,是计算机算法理论历史上的经典问题。在过去几十年中,它成为许多重要算法思想的测试平台,同时也促使一些新的理论领域的产生,比如多面体理论和复杂性理论。 货郎问题:给定n个结点和任意一对结点{i,j}之间的距离为dist(i,j),要求找出一条闭合的回路,该回路经过每个结点一次且仅一次,并且该回路的费用最小,这里的费用是指每段路径的距离和。 货郎问题求解其精确解是NP难的,并且求解任意常数因子近以度的解也是NP难的。若将问题限定在欧氏平面上,就成为欧氏平面上的货郎问题,也叫欧几里德旅行商问题(Eculid Traveling Salesman Problem)。但是,即使是欧氏平面上的货郎问题也是NP难的。因此通常用来解决TSP问题的解法都是近似算法。其中第一个欧几里德旅行商问题的多项式近似算法是Arora在1996年使用随机平面分割和动态规划方法给出的。
J.L. Bentley 建议通过只考虑双调旅程(bitonic tour)来简化问题,这种旅程即为从最左点开始,严格地从左到右直至最右点,然后严格地从右到左直至出发点。下图(b)显示了同样的7个点的最短双调路线。在这种情况下,多项式的算法是可能的。事实上,存在确定的最优双调路线的O(n*n)时间的算法。
注:在一个单位栅格上显示的平面上的七个点。 a)最短闭合路线,长度大约是24.89。这个路线不是双调的。b)相同点的集合上的最短双调闭合路线。长度大约是25.58
下面我以具体的题目为例谈谈双调欧几里德旅行商问题(bitonic tsp):
这个题就是赤裸裸的Bitonic Tour问题了。我的解决方案如下:
将一个人从最左端走到最右端,然后从最右端走到最左端等价成两个人同时从最左端不重复的走过中间的点并且到达最右端。
我们不妨设这两个人为A和B,且总是假定走在前面的人是A。再设函数F(x1, x2)表示A走到x1的位置,B走到x2的位置,并且所有x1,x2之前的位置都被不重复的走过的最短距离之和。根据前面的假设我们可以知道 x1>=x2,且F(xn,xn)即为所得。
下面的过程就是如何推导出状态方程,我把它划分为三种情况:
1) 如果x1=x2,即A和B处在同一点,那么F(x1, x2) = F(x1, x1) = F(x1, x1 - 1) + dist(x1, x1 - 1)
2) 如果x1=x2+1,即B在A的紧邻的靠后一点,那么F(x1, x2) = F(x2, x') + dist(x1, x') (1<= x' <=x2)
3) 如果x1>x2+1,即B离A在后面一个距离的范围以上,那么F(x1, x2) = F(x1 - 1, x2) + dist(x1, x1 - 1)
其实这里不用考虑如果x1,x2走到中间同一个点,因为很容易得到那样不是最优的。
以上算法时间复杂度与空间复杂度均为O(n*n)
这个题和上面的几乎一样,要注意的是,题目并没有说所有的点已经按照x坐标排序,要小心。
这个题目是Bitonic Tour的一个变种,将欧几里德平面的点变成了坐标轴上的点,因此距离函数dist由笛卡尔距离变成了坐标轴距离。另外规则上也有一些变动,只需从左到走到最右,然后反过来从最右把左边所有没走过的走一下。言下之意就是说起点不是固定的。我们不妨假设点的标号为1~n,这里我们虚拟一个起点0,那么问题所求即为 min{F(n,0), F(n,i)+dist(i,n)(1<=i<=n)} 与1不同的是我们的初始条件是F(0,0)=F(1,0)=0,并且在状态转移的过程中要注意从0出发距离是不增加的。
贴下我AC的代码(zju不保存代码:-(,怕以后找不到)
#include#include
constintinf=1000000000;
intn;
intd[128];
intdp[128][128];
intMin(inta,intb)
{
returna
}
intmain()
{
inti, j, k;
while(scanf("%d",&n)&&n)
{
for(i=1; i<=n; i++)
scanf("%d", d+i);
for(i=0; i<=n; i++)
for(j=0; j<=n; j++)
dp[i][j]=inf;
dp[0][0]=dp[1][0]=0;
for(i=2; i<=n; i++)
{
for(j=i-1; j>=0; j--)
dp[i][i-1]=Min(dp[i][i-1], dp[i-1][j]+(j==0?0: abs(d[j]-d[i])));
for(j=0; j<=i-1; j++)
{
dp[i][j]=Min(dp[i][j], dp[i-1][j]+abs(d[i]-d[i-1]));
} }
intans=dp[n][0];
for(i=1; i<=n; i++)
{
ans=Min(ans, dp[n][i]+abs(d[i]-d[n]));
}
printf("%d\n", ans);
}
}
货郎问题java_货郎问题相关推荐
- 货郎问题java_动态规划----货郎担问题
g(2 ,空) = c21 = 5 g(3,空) = c31 = 6 g(4,空) = c41 = 8 由式g( i, S) = min{cij + g( j, S - {j}) } 得 g(2 ...
- 微信聊天记录备份:当前网络状况复杂和连接失败的解决办法
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议 本文链接(文末链接可直达原文): https://blog.csdn.net/qq_41811874/article/detai ...
- 回溯算法 ------回溯算法的几个例子
1.回溯算法的小结 2.回溯算法的几个例子 2.1 ------ 4后问题 搜索空间: 2.2 ------01背包问题 01背包问题的算法设计 01背包问题的实例分析 01背包问题的搜索空间 ...
- 【算法设计与分析】02 货郎问题与计算复杂性理论
什么是NP系列问题?今天来看看这些问题. 文章目录 1 货郎问题 2 0-1背包问题 3 什么是NP-hard问题(NP难问题) 1 货郎问题 问题:有n个城市,已知任何两个城市之间的距离,求一条每个 ...
- 货郎问题和计算复杂度
问题的计算复杂性 货郎问题 问题描述 0-1背包 问题描述 0-1背包问题建模 NP-hard问题 Algorithm + Data Structure = Programming 货郎问题 问题描述 ...
- 货郎问题(暴力求解)
设有m个城市,已知其中任何两个城市之间(不经过第三个城市)道路的距离.一个货郎需要到每个城市巡回卖货,他从某个城市出发,每个城市恰好经过一次,最后回到出发的城市.问怎样走使得总的路程最短. 问题:有穷 ...
- C语言写货郎问题(贪心算法)
这个是用c语言写的求解货郎问题的解,注意这是贪心算法,并不是动态规划,也就是说这个不一定是最优解 #include <stdio.h> #include <stdlib.h> ...
- 货郎问题与计算复杂性
货郎问题与计算复杂性
- 货郎问题:回溯法和限界分支法
这个问题可以堪称一个全排列,[起点,剩下的全排列] 回溯法 import numpy as npclass backtracking_Traveling_saleman:# 初始化,明确起点def _ ...
最新文章
- ejabberd mysql 搭建配置_ejabberd安装步骤+Mysql配置
- python 遍历删除
- MyEclipse Web 项目的图标和右键New菜单
- 访问其他程序中的数据(ContentResolver的CRUD操作)
- [Go语言]从Docker源码学习Go——init()方法和identifier首字母大小写区分
- 本地提交到yarn_Flink on Yarn三部曲之三:提交Flink任务
- hdu 1024(dp)
- gtk_init参数传递过程(草稿)
- 【RT-Thread 作品秀】空气质量监测系统
- cisco privilege权限
- Cookie、Session和Token(学习笔记)
- 人工智能深度神经网络的研究
- 2920集五福_2020年支付宝集五福攻略
- 一位自由职业者的日常
- 解决:Uncaught DOMException: Blocked a frame with origin “xxx“ from accessing a cross-origin frame.
- 制造业的发展战略规划
- 数据结构:线性链表的c语言实现
- Relief特征选择算法
- java中返回值空值(null)处理
- 数组的反转的简单方法