zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    结构体比较
    不定长参数列表用法
    接口
    字符串数据类型
    *和**的打包和解包
    python类常用装饰器
    继承的实现
    map用法
    包的导入和init函数
    协程
  • 原文地址:https://www.cnblogs.com/zhonghaoxi/p/2689985.html
Copyright © 2011-2022 走看看