BYRBT

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 }

 

posted @ 2012-09-18 08:20  zhonghaoxi  阅读(949)  评论(0编辑  收藏  举报
BYRBT