Pentium.Labs

System全家桶:https://zhuanlan.zhihu.com/c_1238468913098731520

导航

poj3502 恶心题

巨恶心的一个题::>_<::

 

题意:给出航班航线和大陆,找航线上距离大陆最远的某一点距离大陆边缘的距离

标准算法:二分答案,从大陆边界向外扩展,扩展出来的面积会覆盖航线。找出航线上最后被覆盖的点即可。

poj讨论版上还有人用模拟退火做的orz

 

自己的YY算法:如图

找出那些航线与大陆边界的交界点,这些交界点把航线又分成了若干线段。从这些线段上找点即可。

这方法是好想可是不好写啊喂>_<

全写完估计800行啊喂>_<

不写了-_-||

 

一开始还有脑洞地去求大陆的凸包,实际上那就错了= =。直接按顺序构造多边形即可

上半成品:

  1 #include<vector>
  2 #include<list>
  3 #include<map>
  4 #include<set>
  5 #include<deque>
  6 #include<queue>
  7 #include<stack>
  8 #include<bitset>
  9 #include<algorithm>
 10 #include<functional>
 11 #include<numeric>
 12 #include<utility>
 13 #include<iostream>
 14 #include<sstream>
 15 #include<iomanip>
 16 #include<cstdio>
 17 #include<cmath>
 18 #include<cstdlib>
 19 #include<cctype>
 20 #include<string>
 21 #include<cstring>
 22 #include<cstdio>
 23 #include<cmath>
 24 #include<cstdlib>
 25 #include<ctime>
 26 #include<climits>
 27 #include<complex>
 28 #define mp make_pair
 29 #define pb push_back
 30 using namespace std;
 31 const double eps=1e-8;//精度
 32 const double pi=acos(-1.0);//π
 33 const double inf=1e20;//无穷大
 34 const int maxp=1111;//最大点数
 35 /*
 36     判断d是否在精度内等于0
 37 */
 38 
 39 bool cmp(double x,double y)
 40 {    return x<y;    }
 41 
 42 int dblcmp(double d)
 43 {
 44     if (fabs(d)<eps)return 0;
 45     return d>eps?1:-1;
 46 }
 47 /*
 48     求x的平方
 49 */
 50 inline double sqr(double x){return x*x;}
 51 /*
 52     点/向量
 53 */
 54 struct point
 55 {
 56     double x,y;
 57     int dis;        //inside(1) OR outside(0) OF the continent
 58     point(){}
 59     point(double _x,double _y):x(_x),y(_y){};
 60     //读入一个点
 61     void input()
 62     {
 63         scanf("%lf%lf",&x,&y);
 64     }
 65     //输出一个点
 66     void output()
 67     {
 68         printf("%.2f %.2f\n",x,y);
 69     }
 70     //判断两点是否相等
 71     bool operator==(point a)const
 72     {
 73         return dblcmp(a.x-x)==0&&dblcmp(a.y-y)==0;
 74     }
 75     //判断两点大小
 76     bool operator<(point a)const
 77     {
 78         return dblcmp(a.x-x)==0?dblcmp(y-a.y)<0:x<a.x;
 79     }
 80     //点到源点的距离/向量的长度
 81     double len()
 82     {
 83         return hypot(x,y);
 84     }
 85     //点到源点距离的平方
 86     double len2()
 87     {
 88         return x*x+y*y;
 89     }
 90     //两点间的距离
 91     double distance(point p)
 92     {
 93         return hypot(x-p.x,y-p.y);
 94     }
 95     //向量加
 96     point add(point p)
 97     {
 98         return point(x+p.x,y+p.y);
 99     }
100     //向量减
101     point sub(point p)
102     {
103         return point(x-p.x,y-p.y);
104     }
105     //向量乘
106     point mul(double b)
107     {
108         return point(x*b,y*b);
109     }
110     //向量除
111     point div(double b)
112     {
113         return point(x/b,y/b);
114     }
115     //点乘
116     double dot(point p)
117     {
118         return x*p.x+y*p.y;
119     }
120     //叉乘
121     double det(point p)
122     {
123         return x*p.y-y*p.x;
124     }
125     //XXXXXXX
126     double rad(point a,point b)
127     {
128         point p=*this;
129         return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
130     }
131     //截取长度r
132     point trunc(double r)
133     {
134         double l=len();
135         if (!dblcmp(l))return *this;
136         r/=l;
137         return point(x*r,y*r);
138     }
139     //左转90度
140     point rotleft()
141     {
142         return point(-y,x);
143     }
144     //右转90度
145     point rotright()
146     {
147         return point(y,-x);
148     }
149     //绕点p逆时针旋转angle角度
150     point rotate(point p,double angle)
151     {
152         point v=this->sub(p);
153         double c=cos(angle),s=sin(angle);
154         return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
155     }
156 };
157 /*
158     线段/直线
159 */
160 struct line
161 {
162     point a,b;
163     line(){}
164     line(point _a,point _b)
165     {
166         a=_a;
167         b=_b;
168     }
169     //判断线段相等
170     bool operator==(line v)
171     {
172         return (a==v.a)&&(b==v.b);
173     }
174     //点p做倾斜角为angle的射线
175     line(point p,double angle)
176     {
177         a=p;
178         if (dblcmp(angle-pi/2)==0)
179         {
180             b=a.add(point(0,1));
181         }
182         else
183         {
184             b=a.add(point(1,tan(angle)));
185         }
186     }
187     //直线一般式ax+by+c=0
188     line(double _a,double _b,double _c)
189     {
190         if (dblcmp(_a)==0)
191         {
192             a=point(0,-_c/_b);
193             b=point(1,-_c/_b);
194         }
195         else if (dblcmp(_b)==0)
196         {
197             a=point(-_c/_a,0);
198             b=point(-_c/_a,1);
199         }
200         else
201         {
202             a=point(0,-_c/_b);
203             b=point(1,(-_c-_a)/_b);
204         }
205     }
206     //读入一个线段
207     void input()
208     {
209         a.input();
210         b.input();
211     }
212     //校准线段两点
213     void adjust()
214     {
215         if (b<a)swap(a,b);
216     }
217     //线段长度
218     double length()
219     {
220         return a.distance(b);
221     }
222     //直线倾斜角 0<=angle<180
223     double angle()
224     {
225         double k=atan2(b.y-a.y,b.x-a.x);
226         if (dblcmp(k)<0)k+=pi;
227         if (dblcmp(k-pi)==0)k-=pi;
228         return k;
229     }
230     //点和线段关系
231     //1 在逆时针
232     //2 在顺时针
233     //3 平行
234     int relation(point p)
235     {
236         int c=dblcmp(p.sub(a).det(b.sub(a)));
237         if (c<0)return 1;
238         if (c>0)return 2;
239         return 3;
240     }
241     //点是否在线段上
242     bool pointonseg(point p)
243     {
244         return dblcmp(p.sub(a).det(b.sub(a)))==0&&dblcmp(p.sub(a).dot(p.sub(b)))<=0;
245     }
246     //两线是否平行
247     bool parallel(line v)
248     {
249         return dblcmp(b.sub(a).det(v.b.sub(v.a)))==0;
250     }
251     //线段和线段关系
252     //0 不相交
253     //1 非规范相交
254     //2 规范相交
255     int segcrossseg(line v)
256     {
257         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
258         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
259         int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
260         int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
261         if ((d1^d2)==-2&&(d3^d4)==-2)return 2;
262         return (d1==0&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=0||
263                 d2==0&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=0||
264                 d3==0&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=0||
265                 d4==0&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=0);
266     }
267     //线段和直线v关系
268     int linecrossseg(line v)//*this seg v line
269     {
270         int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
271         int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
272         if ((d1^d2)==-2)return 2;
273         return (d1==0||d2==0);
274     }
275     //直线和直线关系
276     //0 平行
277     //1 重合
278     //2 相交
279     int linecrossline(line v)
280     {
281         if ((*this).parallel(v))
282         {
283             return v.relation(a)==3;
284         }
285         return 2;
286     }
287     //求两线交点
288     point crosspoint(line v)
289     {
290         double a1=v.b.sub(v.a).det(a.sub(v.a));
291         double a2=v.b.sub(v.a).det(b.sub(v.a));
292         return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
293     }
294     //点p到直线的距离
295     double dispointtoline(point p)
296     {
297         return fabs(p.sub(a).det(b.sub(a)))/length();
298     }
299     //点p到线段的距离
300     double dispointtoseg(point p)
301     {
302         if (dblcmp(p.sub(b).dot(a.sub(b)))<0||dblcmp(p.sub(a).dot(b.sub(a)))<0)
303         {
304             return min(p.distance(a),p.distance(b));
305         }
306         return dispointtoline(p);
307     }
308     //XXXXXXXX
309     point lineprog(point p)
310     {
311         return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));
312     }
313     //点p关于直线的对称点
314     point symmetrypoint(point p)
315     {
316         point q=lineprog(p);
317         return point(2*q.x-p.x,2*q.y-p.y);
318     }
319 };
320 
321 /*
322     多边形
323 */
324 struct polygon
325 {
326     int n;//点个数
327     point p[maxp];//顶点
328     line l[maxp];//329     //读入一个多边形
330     void input()
331     {
332         for (int i=0;i<n;i++)
333         {
334             p[i].input();
335         }
336     }
337     //添加一个点
338     void add(point q)
339     {
340         p[n++]=q;
341     }
342     //取得边
343     void getline()
344     {
345         for (int i=0;i<n;i++)
346         {
347             l[i]=line(p[i],p[(i+1)%n]);
348         }
349     }
350     struct cmp
351     {
352         point p;
353         cmp(const point &p0){p=p0;}
354         bool operator()(const point &aa,const point &bb)
355         {
356             point a=aa,b=bb;
357             int d=dblcmp(a.sub(p).det(b.sub(p)));
358             if (d==0)
359             {
360                 return dblcmp(a.distance(p)-b.distance(p))<0;
361             }
362             return d>0;
363         }
364     };
365     void norm()
366     {
367         point mi=p[0];
368         for (int i=1;i<n;i++)mi=min(mi,p[i]);
369         sort(p,p+n,cmp(mi));
370     }
371     //求凸包存入多边形convex
372     void getconvex(polygon &convex)
373     {
374         int i,j,k;
375         sort(p,p+n);
376         convex.n=n;
377         for (i=0;i<min(n,2);i++)
378         {
379             convex.p[i]=p[i];
380         }
381         if (n<=2)return;
382         int &top=convex.n;
383         top=1;
384         for (i=2;i<n;i++)
385         {
386             while (top&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0)
387                 top--;
388             convex.p[++top]=p[i];
389         }
390         int temp=top;
391         convex.p[++top]=p[n-2];
392         for (i=n-3;i>=0;i--)
393         {
394             while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top-1].sub(p[i]))<=0)
395                 top--;
396             convex.p[++top]=p[i];
397         }
398     }
399     //判断是否凸多边形
400     bool isconvex()
401     {
402         bool s[3];
403         memset(s,0,sizeof(s));
404         int i,j,k;
405         for (i=0;i<n;i++)
406         {
407             j=(i+1)%n;
408             k=(j+1)%n;
409             s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+1]=1;
410             if (s[0]&&s[2])return 0;
411         }
412         return 1;
413     }
414     //点与多边形关系
415     //0 外部
416     //1 内部
417     //2 边上
418     //3 点上
419     int relationpoint(point q)
420     {
421         int i,j;
422         for (i=0;i<n;i++)
423         {
424             if (p[i]==q)return 3;
425         }
426         getline();
427         for (i=0;i<n;i++)
428         {
429             if (l[i].pointonseg(q))return 2;
430         }
431         int cnt=0;
432         for (i=0;i<n;i++)
433         {
434             j=(i+1)%n;
435             int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j])));
436             int u=dblcmp(p[i].y-q.y);
437             int v=dblcmp(p[j].y-q.y);
438             if (k>0&&u<0&&v>=0)cnt++;
439             if (k<0&&v<0&&u>=0)cnt--;
440         }
441         return cnt!=0;
442     }
443     //线段与多边形关系
444     //0 无任何交点
445     //1 在多边形内长度为正
446     //2 相交或与边平行
447     int relationline(line u)
448     {
449         int i,j,k=0;
450         getline();
451         for (i=0;i<n;i++)
452         {
453             if (l[i].segcrossseg(u)==2)return 1;
454             if (l[i].segcrossseg(u)==1)k=1;
455         }
456         if (!k)return 0;
457         vector<point>vp;
458         for (i=0;i<n;i++)
459         {
460             if (l[i].segcrossseg(u))
461             {
462                 if (l[i].parallel(u))
463                 {
464                     vp.pb(u.a);
465                     vp.pb(u.b);
466                     vp.pb(l[i].a);
467                     vp.pb(l[i].b);
468                     continue;
469                 }
470                 vp.pb(l[i].crosspoint(u));
471             }
472         }
473         sort(vp.begin(),vp.end());
474         int sz=vp.size();
475         for (i=0;i<sz-1;i++)
476         {
477             point mid=vp[i].add(vp[i+1]).div(2);
478             if (relationpoint(mid)==1)return 1;
479         }
480         return 2;
481     }
482     //直线u切割凸多边形左侧
483     //注意直线方向
484     void convexcut(line u,polygon &po)
485     {
486         int i,j,k;
487         int &top=po.n;
488         top=0;
489         for (i=0;i<n;i++)
490         {
491             int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a)));
492             int d2=dblcmp(p[(i+1)%n].sub(u.a).det(u.b.sub(u.a)));
493             if (d1>=0)po.p[top++]=p[i];
494             if (d1*d2<0)po.p[top++]=u.crosspoint(line(p[i],p[(i+1)%n]));
495         }
496     }
497     //取得周长
498     double getcircumference()
499     {
500         double sum=0;
501         int i;
502         for (i=0;i<n;i++)
503         {
504             sum+=p[i].distance(p[(i+1)%n]);
505         }
506         return sum;
507     }
508     //取得面积
509     double getarea()
510     {
511         double sum=0;
512         int i;
513         for (i=0;i<n;i++)
514         {
515             sum+=p[i].det(p[(i+1)%n]);
516         }
517         return fabs(sum)/2;
518     }
519     bool getdir()//1代表逆时针 0代表顺时针
520     {
521         double sum=0;
522         int i;
523         for (i=0;i<n;i++)
524         {
525             sum+=p[i].det(p[(i+1)%n]);
526         }
527         if (dblcmp(sum)>0)return 1;
528         return 0;
529     }
530     //取得重心
531     point getbarycentre()
532     {
533         point ret(0,0);
534         double area=0;
535         int i;
536         for (i=1;i<n-1;i++)
537         {
538             double tmp=p[i].sub(p[0]).det(p[i+1].sub(p[0]));
539             if (dblcmp(tmp)==0)continue;
540             area+=tmp;
541             ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp;
542             ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp;
543         }
544         if (dblcmp(area))ret=ret.div(area);
545         return ret;
546     }
547     //点在凸多边形内部的判定
548     int pointinpolygon(point q)
549     {
550         if (getdir())reverse(p,p+n);
551         if (dblcmp(q.sub(p[0]).det(p[n-1].sub(p[0])))==0)
552         {
553             if (line(p[n-1],p[0]).pointonseg(q))return n-1;
554             return -1;
555         }
556         int low=1,high=n-2,mid;
557         while (low<=high)
558         {
559             mid=(low+high)>>1;
560             if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>=0&&dblcmp(q.sub(p[0]).det(p[mid+1].sub(p[0])))<0)
561             {
562                 polygon c;
563                 c.p[0]=p[mid];
564                 c.p[1]=p[mid+1];
565                 c.p[2]=p[0];
566                 c.n=3;
567                 if (c.relationpoint(q))return mid;
568                 return -1;
569             }
570             if (dblcmp(q.sub(p[0]).det(p[mid].sub(p[0])))>0)
571             {
572                 low=mid+1;
573             }
574             else
575             {
576                 high=mid-1;
577             }
578         }
579         return -1;
580     }
581 };
582 
583 struct polygon P[100],R[100];       //P:continent    R:convex of the continent
584 struct point key[100];              //key point
585 int T,C,N,M;
586 
587 
588 int main()
589 {
590     freopen("in.txt","r",stdin);
591 
592     cin>>T;
593     while (T--)
594     {
595         cin>>C>>N;
596         for (int i=1;i<=N;i++)
597             key[i].input();
598         for (int i=1;i<=C;i++)
599         {
600             cin>>M;
601             P[i].n=M;
602             P[i].input();
603             P[i].getline();
604             for (int j=1;j<=N;j++)
605             {
606                 if (P[i].relationpoint(key[j])==0)  //outside
607                     key[j].dis=0;
608                 else
609                     key[j].dis=1;
610             }
611         }
612         double mmx=0,dist;
613         struct line maxLN;
614         for (int i=1;i<N;i++)
615         {
616             struct line LN;
617             LN.a=key[i];    LN.b=key[i+1];
618             int tn=0;
619             double tp[100];
620             for (int j=1;j<=C;j++)      //continent j
621             {
622                 for (int k=0;k<P[j].n;k++)  //line k in continent j
623                 {
624                     line TL=P[j].l[k];
625                     if (LN.segcrossseg(TL)!=0)
626                     {
627                         point tm=LN.crosspoint(TL); //crosspoint of continent && flight route
628                         tp[tn]=key[i].distance(tm);
629                         tn++;
630                     }
631                 }
632             }
633             for (int ii=0;ii<tn;ii++)  printf("%.6f ",tp[ii]);  printf("\n");
634             sort(tp,tp+tn,cmp);
635             for (int ii=0;ii<tn;ii++)  printf("%.6f ",tp[ii]);  printf("\n");
636             if (key[i].dis==0)  //outside
637             {
638                 for (int j=0;j<tn;j=j+2)
639                 {
640                     double TM;
641                     if (j==0)   TM=tp[j];   else TM=tp[j]-tp[j-1];
642                     if (TM>mmx) 
643                     {
644                         maxLN=LN;
645                         mmx=TM;
646                         if (j==0) dist=mmx/2; else dist=tp[j-1]+mmx/2;
647                     }
648                 }
649             }
650             else    //inside
651             {
652                 for (int j=1;j<tn;j=j+2)
653                 {
654                     double TM;
655                     TM=tp[j]-tp[j-1];
656                     if (TM>mmx) 
657                     {
658                         maxLN=LN;
659                         mmx=TM;
660                         dist=tp[j-1]+mmx/2;
661                     }
662                 }
663             }
664         }
665         double dx=maxLN.a.distance(maxLN.b);    dx=dist/dx;
666         point A=maxLN.a,B=maxLN.b;
667         point Ans=(A.x+(B.x-A.x)*dx,A.y+(B.y-A.y)*dy);
668         
669                 
670         printf("%.6f\n",mmx/2);
671     }
672     return 0;
673 }
View Code

 

果然计算几何就是坑坑坑坑T^T

在 http://poj.org/showcontest?contest_id=1477上面找的,实际上这一套题除了A剩下的都是坑= =

posted on 2015-01-23 11:17  Pentium.Labs  阅读(302)  评论(0编辑  收藏  举报



Pentium.Lab Since 1998