• 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
    ",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~

    注定失败的战争,也要拼尽全力去打赢它; 就算输,也要输得足够漂亮。
  • 相关阅读:
    79. 滑动窗口的最大值
    78. 左旋转字符串
    77. 翻转单词顺序
    76. 和为S的连续正数序列
    75. 和为S的两个数字
    innodb 锁机制
    MVCC
    linux查看状态命令
    design pattern 资料整理
    mysql资料汇总
  • 原文地址:https://www.cnblogs.com/yalphait/p/8536308.html
Copyright © 2020-2023  润新知