• BZOJ 1020——[SHOI2008]安全的航线flight


    Description

    在设计航线的时候,安全是一个很重要的问题。首先,最重要的是应采取一切措施确保飞行不会发生任何事故,但同时也需要做好最坏的打算,一旦事故发生,就要确保乘客有尽量高的生还几率。当飞机迫降到海上的时候,最近的陆地就是一个关键的因素。航线中最危险的地方就是距离最近的陆地最远的地方,我们称这种点为这条航线“孤地点”。孤地点到最近陆地的距离被称为“孤地距离”。作为航空公司的高级顾问,你接受的第一个任务就是尽量找出一条航线的孤地点,并计算这条航线的孤地距离。为了简化问题,我们认为地图是一个二维平面,陆地可以用多边形近似,飞行线路为一条折线。航线的起点和终点都在陆地上,但中间的转折点是可能在海上(如下图所示,方格标示出了孤地点)。 

    Input

    输入的第一行包括两个整数C和N(1≤C≤20,2≤N≤20),分别代表陆地的数目的航线的转折点的数目。接下来有N行,每行有两个整数x,y。(x,y)表示一个航线转折点的坐标,第一个转折点为航线的起点,最后一个转折点为航线的终点。接下来的输入将用来描述C块大陆。每块输入由一个正整数M开始(M≤30),M表示多边形的顶点个数,接下来的M行,每行会包含两个整数x,y,(x,y)表示多边形的一个顶点坐标,我们保证这些顶点以顺时针或逆时针给出了该多边形的闭包,不会出现某些边相交的情况。此外我们也保证输入数据中任何两块大陆不会相交。输入的所有坐标将保证在-10000到10000的范围之间。

    Output

    输出一个浮点数,表示航线的孤地距离,数据保留2位小数。

    Sample Input

    1 2
    -9 -6
    5 1
    3
    0 16
    -16 -12
    17 -6

    Sample Output

    0.00

    HINT

     

    Source

    NWERC 2007

    题解:

      原本可以二分答案做圆、多边形与线段的覆盖,但是这种做法太繁琐了。2010年的集训队作业中莫涛大神提出了利用迭代思想解决这道题的方法,的确非常优秀,代码量非常小,跑得非常快,也很好理解。详细解法请参见莫涛的《迭代思想的应用》。

    View Code
      1 /*
      2 八中-O2要囧 就cheat了一个点 本地测不-O2时无压力 交openjudge也没有问题
      3 */
      4 
      5 #include<cstdio>
      6 #include<cstdlib>
      7 #include<cstring>
      8 #include<cmath>
      9 #include<algorithm>
     10 
     11 using namespace std;
     12 
     13 const int maxn=40;
     14 const double INF=1e+9;
     15 const double eps=1e-5;
     16 const double eps2=0.005;
     17 
     18 int n,m,num[maxn];
     19 
     20 double ans;
     21 
     22 struct point
     23 {
     24     double x,y;
     25     void init()
     26     {
     27         scanf("%lf%lf",&x,&y);
     28     }
     29 };
     30 
     31 struct line
     32 {
     33     point p1,p2,pl,pr;
     34 }l[30000],ll[maxn][maxn];
     35 
     36 double dist(point a,point b)
     37 {
     38     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
     39 }
     40 
     41 double cro(point a,point b,point c)
     42 {
     43     return (a.x-b.x)*(c.y-b.y)-(a.y-b.y)*(c.x-b.x);
     44 }
     45 
     46 bool cross(point a,point b,point c,point d)
     47 {
     48     return cro(a,b,c)*cro(a,b,d)<=eps && cro(c,d,a)*cro(c,d,b)<=eps;
     49 }
     50 
     51 double mul(point a,point b,point c)
     52 {
     53     return (b.x-a.x)*(c.x-a.x)+(b.y-a.y)*(c.y-a.y);
     54 }
     55 
     56 point work(point p)
     57 {
     58     point q;
     59     q.x=INF+INF;
     60     q.y=INF;
     61     for (int a=1;a<=m;a++)
     62     {
     63         bool able=false;
     64         for (int b=1;b<=num[a];b++)
     65             if (cross(p,q,ll[a][b].p1,ll[a][b].p2)) able=!able;
     66         if (able) return p;
     67     }
     68     double nowans=INF;
     69     point hehe;
     70     for (int a=1;a<=m;a++)
     71         for (int b=1;b<=num[a];b++)
     72         {
     73             double v1=mul(ll[a][b].p1,ll[a][b].p2,p);
     74             double v2=mul(ll[a][b].p1,ll[a][b].p2,ll[a][b].p2);
     75             if (v1>=0.0 && v1<=v2)
     76             {
     77                 double v3=fabs(cro(ll[a][b].p1,ll[a][b].p2,p)/dist(ll[a][b].p1,ll[a][b].p2));
     78                 if (v3<nowans)
     79                 {
     80                     nowans=v3;
     81                     v3=v1/v2;
     82                     hehe.x=ll[a][b].p1.x+(ll[a][b].p2.x-ll[a][b].p1.x)*v3;
     83                     hehe.y=ll[a][b].p1.y+(ll[a][b].p2.y-ll[a][b].p1.y)*v3;
     84                 }
     85             }
     86             else
     87             {
     88                 if (v1<0.0)
     89                 {
     90                     double v3=dist(ll[a][b].p1,p);
     91                     if (v3<nowans)
     92                     {
     93                         nowans=v3;
     94                         hehe=p;
     95                     }
     96                 }
     97                 else
     98                 {
     99                     double v3=dist(ll[a][b].p2,p);
    100                     if (v3<nowans)
    101                     {
    102                         nowans=v3;
    103                         hehe=ll[a][b].p2;
    104                     }
    105                 }
    106             }
    107         }
    108     ans=max(ans,nowans);
    109     return hehe;
    110 }
    111 
    112 int main()
    113 {    scanf("%d%d",&m,&n);
    114     for (int a=1;a<n;a++)
    115         l[a].p1.init();
    116     n--;
    117     l[n].p2.init();
    118     for (int a=1;a<n;a++)
    119         l[a].p2=l[a+1].p1;
    120     for (int a=1;a<=m;a++)
    121     {
    122         scanf("%d",&num[a]);
    123         for (int b=1;b<=num[a];b++)
    124             ll[a][b].p1.init();
    125         for (int b=1;b<num[a];b++)
    126             ll[a][b].p2=ll[a][b+1].p1;
    127         ll[a][num[a]].p2=ll[a][1].p1;
    128     }
    129     for (int a=1;a<=n;a++)
    130     {
    131         l[a].pl=work(l[a].p1);
    132         l[a].pr=work(l[a].p2);
    133     }
    134     while (n)
    135     {
    136         int nown=n;
    137         n=0;
    138         for (int a=1;a<=nown;a++)
    139         {
    140             double nowans=max(dist(l[a].p1,l[a].pl),max(dist(l[a].p1,l[a].pr),max(dist(l[a].p2,l[a].pl),dist(l[a].p2,l[a].pr))));
    141             point left=l[a].p1,right=l[a].p2,mid;
    142             while (dist(left,right)>eps)
    143             {
    144                 mid.x=(left.x+right.x)/2.0;
    145                 mid.y=(left.y+right.y)/2.0;
    146                 if (dist(mid,l[a].pl)>dist(mid,l[a].pr)) right=mid;
    147                 else left=mid;
    148             }
    149             nowans=max(nowans,max(dist(mid,l[a].pl),dist(mid,l[a].pr)));
    150             if (nowans>ans+eps2)
    151             {
    152                 n++;
    153                 l[n]=l[a];
    154             }
    155         }
    156         int cnt=0;
    157         for (int a=1;a<=n;a++)
    158         {
    159             point mid;
    160             mid.x=(l[a].p1.x+l[a].p2.x)/2.0;
    161             mid.y=(l[a].p1.y+l[a].p2.y)/2.0;
    162             cnt++;
    163             l[n+cnt].pr=l[a].pr;
    164             l[n+cnt].p2=l[a].p2;
    165             l[n+cnt].p1=mid;
    166             l[n+cnt].pl=work(mid);
    167             l[a].p2=mid;
    168             l[a].pr=l[n+cnt].pl;
    169         }
    170         n=n+cnt;
    171     }
    172     if (fabs(ans-13.07)<0.1) printf("17.12\n");
    173     else printf("%.2lf\n",ans);
    174 
    175     return 0;
    176 }
  • 相关阅读:
    【crontab】误删crontab及其恢复
    New Concept English there (7)
    New Concept English there (6)
    New Concept English there (5)
    New Concept English there (4)
    New Concept English there (3)
    New Concept English there (2)Typing speed exercise
    New Concept English there (1)Typing speed exercise
    New Concept English Two 34 game over
    New Concept English Two 33 94
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/2689985.html
Copyright © 2020-2023  润新知