bzoj 1020 计算几何
2016-08-17 18:35
381 查看
题意:一堆多边形,一个折线。求折线上的点离多边形最远距离。
听说莫涛的论文写了这道题?
先把折线中所有的线段用多边形截,把不在多边形内的线段塞到一个队列里。
遍历队列,对于一个线段求出左端点到多边形的最近点p1,右端点到多边形的最近点p2。
分别用左右端点到p1,p2的距离更新答案。在线段上二分一个点p使dis(p,p1)=dis(p,p2)。
如果dis(p,p1)>ans那么把当前线段从p分成两段塞回队列。
并不会证明,但是这玩意跑得飞快。
听说莫涛的论文写了这道题?
先把折线中所有的线段用多边形截,把不在多边形内的线段塞到一个队列里。
遍历队列,对于一个线段求出左端点到多边形的最近点p1,右端点到多边形的最近点p2。
分别用左右端点到p1,p2的距离更新答案。在线段上二分一个点p使dis(p,p1)=dis(p,p2)。
如果dis(p,p1)>ans那么把当前线段从p分成两段塞回队列。
并不会证明,但是这玩意跑得飞快。
#include <bits/stdc++.h> using namespace std; #define ppi pair<poi,int> #define eps 1e-9 #define inf 1e9 int c,n,cnt; double ans; const double e=exp(1),pi=acos(-1); int dcmp(double x) { if(x<-eps)return -1; if(x>eps)return 1; return 0; } struct poi { double x,y; poi(){} poi(double x,double y):x(x),y(y){} friend bool operator < (const poi &p1,const poi &p2) { if(!dcmp(p1.x-p2.x))return p1.y<p2.y; return p1.x<p2.x; } void read(){scanf("%lf%lf",&x,&y);} friend poi operator - (const poi &p1,const poi &p2) {return poi(p1.x-p2.x,p1.y-p2.y);}; friend poi operator + (const poi &p1,const poi &p2) {return poi(p1.x+p2.x,p1.y+p2.y);}; friend double operator * (const poi &p1,const poi &p2) {return p1.x*p2.x+p1.y*p2.y;}; friend double operator ^ (const poi &p1,const poi &p2) {return p1.x*p2.y-p2.x*p1.y;}; friend poi operator * (double x,const poi &p1) {return poi(p1.x*x,p1.y*x);}; }v[2100]; double dis(poi p1,poi p2) {return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);} struct line { poi p1,p2,v; line(){} line(poi p1,poi p2):p1(p1),p2(p2){v=p1-p2;} poi mid(){return poi((p1.x+p2.x)/2,(p1.y+p2.y)/2);} }a[51]; queue<line>que; int online(line l1,poi p1) {return dcmp((p1-l1.p1)*(p1-l1.p2))<=0;} ppi intersect(line l1,line l2) { l1.v=l1.p1-l1.p2; l2.v=l2.p1-l2.p2; poi u=l1.p1-l2.p1; double tmp=(u^l2.v)/(l2.v^l1.v); poi p=l1.p1+tmp*l1.v; return make_pair(p,online(l1,p)&&online(l2,p)); } struct poly { int m; poi p[51]; line l[51]; void read() { scanf("%d",&m); for(int i=1;i<=m;i++)p[i].read(); p[m+1]=p[1]; for(int i=1;i<=m;i++)l[i]=line(p[i],p[i+1]); } void cal(line l1) { for(int i=1;i<=m;i++) { ppi p1=intersect(l[i],l1); if(p1.second)v[++cnt]=p1.first; } } int in(poi p1) { int cnt=0; line l1=line(p1,poi(p1.x+e*inf,p1.y+pi*inf)); for(int i=1;i<=m;i++) cnt+=intersect(l1,l[i]).second; return cnt&1; } poi get(poi p1) { poi ret=poi(inf,inf); for(int i=1;i<=m;i++) { ret=dis(ret,p1)<dis(l[i].p1,p1) ? ret:l[i].p1; ret=dis(ret,p1)<dis(l[i].p2,p1) ? ret:l[i].p2; poi p2=poi(p1.x-l[i].p2.y+l[i].p1.y,p1.y+l[i].p2.x-l[i].p1.x); ppi p=intersect(l[i],line(p1,p2)); if(online(l[i],p.first)) ret=dis(ret,p1)<dis(p.first,p1) ? ret:p.first; } return ret; } }b[51]; int main() { //freopen("tt.in","r",stdin); scanf("%d%d",&c,&n); for(int i=1;i<n;i++)a[i].p1.read(); a[n-1].p2.read(); for(int i=1;i<n-1;i++)a[i].p2=a[i+1].p1; for(int i=1;i<=c;i++)b[i].read(); for(int i=1;i<n;i++) { v[cnt=1]=a[i].p1; for(int j=1;j<=c;j++) b[j].cal(a[i]); v[++cnt]=a[i].p2; sort(v+1,v+1+cnt); for(int j=1;j<cnt;j++) if(dcmp(dis(v[j],v[j+1]))>0) { int flag=0; for(int k=1;k<=c;k++) if(b[k].in(line(v[j],v[j+1]).mid())) {flag=1;break;} if(!flag)que.push(line(v[j],v[j+1])); } } while(!que.empty()) { line l1=que.front(); que.pop(); poi p1=poi(inf,inf),p2=p1; for(int i=1;i<=c;i++) { poi p=b[i].get(l1.p1); p1=dis(p1,l1.p1)<dis(p,l1.p1) ? p1:p; p=b[i].get(l1.p2); p2=dis(p2,l1.p2)<dis(p,l1.p2) ? p2:p; } ans=max(ans,sqrt(dis(p1,l1.p1))); ans=max(ans,sqrt(dis(p2,l1.p2))); poi l=l1.p1,r=l1.p2; while(dcmp(dis(l,r))>0) { poi mid=line(l,r).mid(); if(dis(mid,p1)<dis(mid,p2))l=mid; else r=mid; } if(sqrt(dis(l,p1))>ans+0.001) { que.push(line(l,l1.p1)); que.push(line(l,l1.p2)); } } printf("%.2lf\n",ans); return 0; }
相关文章推荐
- 初学算法 - 求凸包的Garham's Scan算法的C++实现
- 【Google Code Jam 2009 round2 problem D】Watering Plants (两圆交点求法详解)
- 计算几何模板
- 计算几何小模板
- BZOJ2829信用卡凸包
- Farthest Point
- HDU 4922 Hello, Your Package! (计算几何+DP)(WA)
- poj 1514&zoj 1185 Metal Cutting(半平面交)
- UVA 10969 Sweet Dream(圆的相交)
- uva 11177 Fighting Against a Polygonal Monster(凸包与圆的面积交)
- POJ1279 && LA2512 Art Gallery(求多边形的核)
- poj 2540 && uva 10084 Hotter Colder(半平面交)
- UVALive 5878 - Shortest Leash 【计算几何】
- 【计算几何】POJ 2318 & POJ 2398
- 【计算几何】POJ 2653
- 【计算几何】POJ 1113
- HDU 5128 The E-pang Palace
- POJ 2318 TOYS(叉积+二分or暴力)
- POJ 2398 Toy Storage(叉积+二分)
- POJ 1228 Grandpa's Estate 计算凸包+判断点在线段上