首页 > 代码库 > poj3502 恶心题
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 //XXXXXXX126 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 //截取长度r132 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 line161 {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 else183 {184 b=a.add(point(1,tan(angle)));185 }186 }187 //直线一般式ax+by+c=0188 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 else201 {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<180223 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 line269 {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 //XXXXXXXX309 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 polygon325 {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 cmp351 {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 //求凸包存入多边形convex372 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 else575 {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 continent584 struct point key[100]; //key point585 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) //outside607 key[j].dis=0;608 else609 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 j621 {622 for (int k=0;k<P[j].n;k++) //line k in continent j623 {624 line TL=P[j].l[k];625 if (LN.segcrossseg(TL)!=0)626 {627 point tm=LN.crosspoint(TL); //crosspoint of continent && flight route628 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) //outside637 {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 //inside651 {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 }
果然计算几何就是坑坑坑坑T^T
在 http://poj.org/showcontest?contest_id=1477上面找的,实际上这一套题除了A剩下的都是坑= =
poj3502 恶心题
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。