巨恶心的一个题::>_<::
题意:给出航班航线和大陆,找航线上距离大陆最远的某一点距离大陆边缘的距离
标准算法:二分答案,从大陆边界向外扩展,扩展出来的面积会覆盖航线。找出航线上最后被覆盖的点即可。
poj讨论版上还有人用模拟退火做的orz
自己的YY算法:如图
找出那些航线与大陆边界的交界点,这些交界点把航线又分成了若干线段。从这些线段上找点即可。
这方法是好想可是不好写啊喂>_<
全写完估计800行啊喂>_<
不写了-_-||
一开始还有脑洞地去求大陆的凸包,实际上那就错了= =。直接按顺序构造多边形即可
上半成品:
#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<iostream>
#include<sstream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cctype>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<ctime>
#include<climits>
#include<complex>
#define mp make_pair
#define pb push_back
using namespace std;
const double eps=1e-;//精度
const double pi=acos(-1.0);//π
const double inf=1e20;//无穷大
const int maxp=;//最大点数
/*
判断d是否在精度内等于0
*/ bool cmp(double x,double y)
{ return x<y; } int dblcmp(double d)
{
if (fabs(d)<eps)return ;
return d>eps?:-;
}
/*
求x的平方
*/
inline double sqr(double x){return x*x;}
/*
点/向量
*/
struct point
{
double x,y;
int dis; //inside(1) OR outside(0) OF the continent
point(){}
point(double _x,double _y):x(_x),y(_y){};
//读入一个点
void input()
{
scanf("%lf%lf",&x,&y);
}
//输出一个点
void output()
{
printf("%.2f %.2f\n",x,y);
}
//判断两点是否相等
bool operator==(point a)const
{
return dblcmp(a.x-x)==&&dblcmp(a.y-y)==;
}
//判断两点大小
bool operator<(point a)const
{
return dblcmp(a.x-x)==?dblcmp(y-a.y)<:x<a.x;
}
//点到源点的距离/向量的长度
double len()
{
return hypot(x,y);
}
//点到源点距离的平方
double len2()
{
return x*x+y*y;
}
//两点间的距离
double distance(point p)
{
return hypot(x-p.x,y-p.y);
}
//向量加
point add(point p)
{
return point(x+p.x,y+p.y);
}
//向量减
point sub(point p)
{
return point(x-p.x,y-p.y);
}
//向量乘
point mul(double b)
{
return point(x*b,y*b);
}
//向量除
point div(double b)
{
return point(x/b,y/b);
}
//点乘
double dot(point p)
{
return x*p.x+y*p.y;
}
//叉乘
double det(point p)
{
return x*p.y-y*p.x;
}
//XXXXXXX
double rad(point a,point b)
{
point p=*this;
return fabs(atan2(fabs(a.sub(p).det(b.sub(p))),a.sub(p).dot(b.sub(p))));
}
//截取长度r
point trunc(double r)
{
double l=len();
if (!dblcmp(l))return *this;
r/=l;
return point(x*r,y*r);
}
//左转90度
point rotleft()
{
return point(-y,x);
}
//右转90度
point rotright()
{
return point(y,-x);
}
//绕点p逆时针旋转angle角度
point rotate(point p,double angle)
{
point v=this->sub(p);
double c=cos(angle),s=sin(angle);
return point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
}
};
/*
线段/直线
*/
struct line
{
point a,b;
line(){}
line(point _a,point _b)
{
a=_a;
b=_b;
}
//判断线段相等
bool operator==(line v)
{
return (a==v.a)&&(b==v.b);
}
//点p做倾斜角为angle的射线
line(point p,double angle)
{
a=p;
if (dblcmp(angle-pi/)==)
{
b=a.add(point(,));
}
else
{
b=a.add(point(,tan(angle)));
}
}
//直线一般式ax+by+c=0
line(double _a,double _b,double _c)
{
if (dblcmp(_a)==)
{
a=point(,-_c/_b);
b=point(,-_c/_b);
}
else if (dblcmp(_b)==)
{
a=point(-_c/_a,);
b=point(-_c/_a,);
}
else
{
a=point(,-_c/_b);
b=point(,(-_c-_a)/_b);
}
}
//读入一个线段
void input()
{
a.input();
b.input();
}
//校准线段两点
void adjust()
{
if (b<a)swap(a,b);
}
//线段长度
double length()
{
return a.distance(b);
}
//直线倾斜角 0<=angle<180
double angle()
{
double k=atan2(b.y-a.y,b.x-a.x);
if (dblcmp(k)<)k+=pi;
if (dblcmp(k-pi)==)k-=pi;
return k;
}
//点和线段关系
//1 在逆时针
//2 在顺时针
//3 平行
int relation(point p)
{
int c=dblcmp(p.sub(a).det(b.sub(a)));
if (c<)return ;
if (c>)return ;
return ;
}
//点是否在线段上
bool pointonseg(point p)
{
return dblcmp(p.sub(a).det(b.sub(a)))==&&dblcmp(p.sub(a).dot(p.sub(b)))<=;
}
//两线是否平行
bool parallel(line v)
{
return dblcmp(b.sub(a).det(v.b.sub(v.a)))==;
}
//线段和线段关系
//0 不相交
//1 非规范相交
//2 规范相交
int segcrossseg(line v)
{
int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
int d3=dblcmp(v.b.sub(v.a).det(a.sub(v.a)));
int d4=dblcmp(v.b.sub(v.a).det(b.sub(v.a)));
if ((d1^d2)==-&&(d3^d4)==-)return ;
return (d1==&&dblcmp(v.a.sub(a).dot(v.a.sub(b)))<=||
d2==&&dblcmp(v.b.sub(a).dot(v.b.sub(b)))<=||
d3==&&dblcmp(a.sub(v.a).dot(a.sub(v.b)))<=||
d4==&&dblcmp(b.sub(v.a).dot(b.sub(v.b)))<=);
}
//线段和直线v关系
int linecrossseg(line v)//*this seg v line
{
int d1=dblcmp(b.sub(a).det(v.a.sub(a)));
int d2=dblcmp(b.sub(a).det(v.b.sub(a)));
if ((d1^d2)==-)return ;
return (d1==||d2==);
}
//直线和直线关系
//0 平行
//1 重合
//2 相交
int linecrossline(line v)
{
if ((*this).parallel(v))
{
return v.relation(a)==;
}
return ;
}
//求两线交点
point crosspoint(line v)
{
double a1=v.b.sub(v.a).det(a.sub(v.a));
double a2=v.b.sub(v.a).det(b.sub(v.a));
return point((a.x*a2-b.x*a1)/(a2-a1),(a.y*a2-b.y*a1)/(a2-a1));
}
//点p到直线的距离
double dispointtoline(point p)
{
return fabs(p.sub(a).det(b.sub(a)))/length();
}
//点p到线段的距离
double dispointtoseg(point p)
{
if (dblcmp(p.sub(b).dot(a.sub(b)))<||dblcmp(p.sub(a).dot(b.sub(a)))<)
{
return min(p.distance(a),p.distance(b));
}
return dispointtoline(p);
}
//XXXXXXXX
point lineprog(point p)
{
return a.add(b.sub(a).mul(b.sub(a).dot(p.sub(a))/b.sub(a).len2()));
}
//点p关于直线的对称点
point symmetrypoint(point p)
{
point q=lineprog(p);
return point(*q.x-p.x,*q.y-p.y);
}
}; /*
多边形
*/
struct polygon
{
int n;//点个数
point p[maxp];//顶点
line l[maxp];//边
//读入一个多边形
void input()
{
for (int i=;i<n;i++)
{
p[i].input();
}
}
//添加一个点
void add(point q)
{
p[n++]=q;
}
//取得边
void getline()
{
for (int i=;i<n;i++)
{
l[i]=line(p[i],p[(i+)%n]);
}
}
struct cmp
{
point p;
cmp(const point &p0){p=p0;}
bool operator()(const point &aa,const point &bb)
{
point a=aa,b=bb;
int d=dblcmp(a.sub(p).det(b.sub(p)));
if (d==)
{
return dblcmp(a.distance(p)-b.distance(p))<;
}
return d>;
}
};
void norm()
{
point mi=p[];
for (int i=;i<n;i++)mi=min(mi,p[i]);
sort(p,p+n,cmp(mi));
}
//求凸包存入多边形convex
void getconvex(polygon &convex)
{
int i,j,k;
sort(p,p+n);
convex.n=n;
for (i=;i<min(n,);i++)
{
convex.p[i]=p[i];
}
if (n<=)return;
int &top=convex.n;
top=;
for (i=;i<n;i++)
{
while (top&&convex.p[top].sub(p[i]).det(convex.p[top-].sub(p[i]))<=)
top--;
convex.p[++top]=p[i];
}
int temp=top;
convex.p[++top]=p[n-];
for (i=n-;i>=;i--)
{
while (top!=temp&&convex.p[top].sub(p[i]).det(convex.p[top-].sub(p[i]))<=)
top--;
convex.p[++top]=p[i];
}
}
//判断是否凸多边形
bool isconvex()
{
bool s[];
memset(s,,sizeof(s));
int i,j,k;
for (i=;i<n;i++)
{
j=(i+)%n;
k=(j+)%n;
s[dblcmp(p[j].sub(p[i]).det(p[k].sub(p[i])))+]=;
if (s[]&&s[])return ;
}
return ;
}
//点与多边形关系
//0 外部
//1 内部
//2 边上
//3 点上
int relationpoint(point q)
{
int i,j;
for (i=;i<n;i++)
{
if (p[i]==q)return ;
}
getline();
for (i=;i<n;i++)
{
if (l[i].pointonseg(q))return ;
}
int cnt=;
for (i=;i<n;i++)
{
j=(i+)%n;
int k=dblcmp(q.sub(p[j]).det(p[i].sub(p[j])));
int u=dblcmp(p[i].y-q.y);
int v=dblcmp(p[j].y-q.y);
if (k>&&u<&&v>=)cnt++;
if (k<&&v<&&u>=)cnt--;
}
return cnt!=;
}
//线段与多边形关系
//0 无任何交点
//1 在多边形内长度为正
//2 相交或与边平行
int relationline(line u)
{
int i,j,k=;
getline();
for (i=;i<n;i++)
{
if (l[i].segcrossseg(u)==)return ;
if (l[i].segcrossseg(u)==)k=;
}
if (!k)return ;
vector<point>vp;
for (i=;i<n;i++)
{
if (l[i].segcrossseg(u))
{
if (l[i].parallel(u))
{
vp.pb(u.a);
vp.pb(u.b);
vp.pb(l[i].a);
vp.pb(l[i].b);
continue;
}
vp.pb(l[i].crosspoint(u));
}
}
sort(vp.begin(),vp.end());
int sz=vp.size();
for (i=;i<sz-;i++)
{
point mid=vp[i].add(vp[i+]).div();
if (relationpoint(mid)==)return ;
}
return ;
}
//直线u切割凸多边形左侧
//注意直线方向
void convexcut(line u,polygon &po)
{
int i,j,k;
int &top=po.n;
top=;
for (i=;i<n;i++)
{
int d1=dblcmp(p[i].sub(u.a).det(u.b.sub(u.a)));
int d2=dblcmp(p[(i+)%n].sub(u.a).det(u.b.sub(u.a)));
if (d1>=)po.p[top++]=p[i];
if (d1*d2<)po.p[top++]=u.crosspoint(line(p[i],p[(i+)%n]));
}
}
//取得周长
double getcircumference()
{
double sum=;
int i;
for (i=;i<n;i++)
{
sum+=p[i].distance(p[(i+)%n]);
}
return sum;
}
//取得面积
double getarea()
{
double sum=;
int i;
for (i=;i<n;i++)
{
sum+=p[i].det(p[(i+)%n]);
}
return fabs(sum)/;
}
bool getdir()//1代表逆时针 0代表顺时针
{
double sum=;
int i;
for (i=;i<n;i++)
{
sum+=p[i].det(p[(i+)%n]);
}
if (dblcmp(sum)>)return ;
return ;
}
//取得重心
point getbarycentre()
{
point ret(,);
double area=;
int i;
for (i=;i<n-;i++)
{
double tmp=p[i].sub(p[]).det(p[i+].sub(p[]));
if (dblcmp(tmp)==)continue;
area+=tmp;
ret.x+=(p[].x+p[i].x+p[i+].x)/*tmp;
ret.y+=(p[].y+p[i].y+p[i+].y)/*tmp;
}
if (dblcmp(area))ret=ret.div(area);
return ret;
}
//点在凸多边形内部的判定
int pointinpolygon(point q)
{
if (getdir())reverse(p,p+n);
if (dblcmp(q.sub(p[]).det(p[n-].sub(p[])))==)
{
if (line(p[n-],p[]).pointonseg(q))return n-;
return -;
}
int low=,high=n-,mid;
while (low<=high)
{
mid=(low+high)>>;
if (dblcmp(q.sub(p[]).det(p[mid].sub(p[])))>=&&dblcmp(q.sub(p[]).det(p[mid+].sub(p[])))<)
{
polygon c;
c.p[]=p[mid];
c.p[]=p[mid+];
c.p[]=p[];
c.n=;
if (c.relationpoint(q))return mid;
return -;
}
if (dblcmp(q.sub(p[]).det(p[mid].sub(p[])))>)
{
low=mid+;
}
else
{
high=mid-;
}
}
return -;
}
}; struct polygon P[],R[]; //P:continent R:convex of the continent
struct point key[]; //key point
int T,C,N,M; int main()
{
freopen("in.txt","r",stdin); cin>>T;
while (T--)
{
cin>>C>>N;
for (int i=;i<=N;i++)
key[i].input();
for (int i=;i<=C;i++)
{
cin>>M;
P[i].n=M;
P[i].input();
P[i].getline();
for (int j=;j<=N;j++)
{
if (P[i].relationpoint(key[j])==) //outside
key[j].dis=;
else
key[j].dis=;
}
}
double mmx=,dist;
struct line maxLN;
for (int i=;i<N;i++)
{
struct line LN;
LN.a=key[i]; LN.b=key[i+];
int tn=;
double tp[];
for (int j=;j<=C;j++) //continent j
{
for (int k=;k<P[j].n;k++) //line k in continent j
{
line TL=P[j].l[k];
if (LN.segcrossseg(TL)!=)
{
point tm=LN.crosspoint(TL); //crosspoint of continent && flight route
tp[tn]=key[i].distance(tm);
tn++;
}
}
}
for (int ii=;ii<tn;ii++) printf("%.6f ",tp[ii]); printf("\n");
sort(tp,tp+tn,cmp);
for (int ii=;ii<tn;ii++) printf("%.6f ",tp[ii]); printf("\n");
if (key[i].dis==) //outside
{
for (int j=;j<tn;j=j+)
{
double TM;
if (j==) TM=tp[j]; else TM=tp[j]-tp[j-];
if (TM>mmx)
{
maxLN=LN;
mmx=TM;
if (j==) dist=mmx/; else dist=tp[j-]+mmx/;
}
}
}
else //inside
{
for (int j=;j<tn;j=j+)
{
double TM;
TM=tp[j]-tp[j-];
if (TM>mmx)
{
maxLN=LN;
mmx=TM;
dist=tp[j-]+mmx/;
}
}
}
}
double dx=maxLN.a.distance(maxLN.b); dx=dist/dx;
point A=maxLN.a,B=maxLN.b;
point Ans=(A.x+(B.x-A.x)*dx,A.y+(B.y-A.y)*dy); printf("%.6f\n",mmx/);
}
return ;
}
果然计算几何就是坑坑坑坑T^T
在 http://poj.org/showcontest?contest_id=1477上面找的,实际上这一套题除了A剩下的都是坑= =