18.03.09 vijos1014旅行商简化版

Posted TobicYAL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了18.03.09 vijos1014旅行商简化版相关的知识,希望对你有一定的参考价值。

背景

欧几里德旅行商(Euclidean Traveling Salesman)问题也就是货郎担问题一直是困扰全世界数学家、计算机学家的著名问题。现有的算法都没有办法在确定型机器上在多项式时间内求出最优解,但是有办法在多项式时间内求出一个较优解。

为了简化问题,而且保证能在多项式时间内求出最优解,J.L.Bentley提出了一种叫做bitonic tour的哈密尔顿环游。它的要求是任意两点(a,b)之间的相互到达的代价dist(a,b)=dist(b,a)且任意两点之间可以相互到达,并且环游的路线只能是从最西端单向到最东端,再单项返回最西端,并且是一个哈密尔顿回路。

描述

著名的NPC难题的简化版本

现在笛卡尔平面上有n(n<=1000)个点,每个点的坐标为(x,y)(-2^31<x,y<2^31,且为整数),任意两点之间相互到达的代价为这两点的欧几里德距离,现要你编程求出最短bitonic tour。

格式

输入格式

第一行一个整数n

接下来n行,每行两个整数x,y,表示某个点的坐标。

输入中保证没有重复的两点,
保证最西端和最东端都只有一个点。

输出格式

一行,即最短回路的长度,保留2位小数。

样例1

样例输入1

7
0 6
1 0
2 3
5 4
6 1
7 5
8 2

样例输出1

25.58

限制

1s

来源

《算法导论(第二版)》 15-1

技术分享图片
 1 #include <iostream>
 2 #include <string.h>
 3 #include <cstdio>
 4 #include <stdlib.h>
 5 #include <algorithm>
 6 #include <math.h>
 7 
 8 using namespace std;
 9 struct area
10 {
11     int x,y;//坐标 (x,y)
12 };
13 
14 double f[1002][1002],dis[1002][1002];
15 const double INF=1e30;
16 double ans=INF;
17 
18 bool comp(const area &q,const area &w)
19 {
20     return q.x<w.x;
21 }
22 
23 int main()
24 {
25     int n;
26     cin>>n;
27     area poi[1002];
28     for(int i=1;i<=n;i++)
29         cin>>poi[i].x>>poi[i].y;
30     sort(poi+1,poi+n+1,comp);
31     for(int i=1;i<=n-1;i++)
32         for(int j=i+1;j<=n;j++)
33         {
34             int x1=poi[i].x,x2=poi[j].x,y1=poi[i].y,y2=poi[j].y;
35             dis[i][j]=sqrt(fabs(x1-x2)*fabs(x1-x2)+fabs(y1-y2)*fabs(y1-y2));
36             f[i][j]=ans;
37         }
38     f[1][2]=dis[1][2];
39     for(int i=1;i<=n;i++)
40         for(int j=i+1;j<=n;j++)//默认f数组前一个参数比后一个参数小
41         {
42             f[i][j+1]=min(f[i][j]+dis[j][j+1],f[i][j+1]);
43             f[j][j+1]=min(f[i][j]+dis[i][j+1],f[j][j+1]);
44         }
45     double min0=INF;
46     for(int i=1;i<=n-1;i++)
47     {
48         min0=min(f[i][n]+dis[i][n],min0);
49     }
50     printf("%.2f\n",min0);
51     return 0;
52 }
View Code

为了防止自己做题以后全部忘掉(而这显然是总是这样) 今天开始较难的题目都要写简单的思路

首先是wa点:

Sort函数有三个参数:
(1)第一个是要排序的数组的起始地址。
(2)第二个是结束的地址(最后一位要排序的地址的下一地址
(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。

被这个wa了两次呢:)

思路:

首先将所有点以x由小到大排序编号

很容易想到:所有的点,除了首尾都会被分为两份,为了便于解出就将这两份看做是两个人行走的不同轨迹,某点不是在甲走的路上就是在乙走的路上

便于记录,事先规定f[][]前面一个参数要比后一个小

初始化i到j的距离数组dis[][](i<j,当然你i>j的时候也存也没事)

于是容易得出动规方程

f[i][j+1]=min(f[i][j]+dis[j][j+1],f[i][j+1])    (当本来在j点的人走到了j+1点)

f[i][j+1]=min(f[i][j]+dis[i][j+1],f[i][j+1])    (当本来在i点的人走到了j+1点)

这样就很简单了,接下来你最终能得到f所有第二个参数为n的值,然后找出其中的最小值就可以啦

end~

以上是关于18.03.09 vijos1014旅行商简化版的主要内容,如果未能解决你的问题,请参考以下文章

旅行商问题 状压DP

#18.03.09 vijos1011清帝之惑之顺治

算法学习双调欧几里得旅行商问题(动态规划)(转)

vijos 1780 开车旅行

vijos1746 floyd

Codevs1041&&Vijos1119 car的旅行路线(最短路dijkstra)