[模板]计算几何
平面最近点对
将平面内点按\(x\)坐标排序,分治\(x\)坐标,设\(ret=min(f(l,mid),f(mid+1,r))\),将\(x\in[mid-ret,mid+ret]\)内的点按\(y\)坐标排序,算每个点与相邻的\(6\)个点的距离找最优解即可.
时间复杂度:\(O(nlogn)\).
#define N 100005
#define INF 1e15
struct point{
double x,y;
}p[N];
inline double sqr(double k){
return k*k;
}
inline double dis(point x,point y){
return sqrt(sqr(x.x-y.x)+sqr(x.y-y.y));
}
inline bool cmpx(point x,point y){
if(x.x!=y.x) return x.x>1;
ret=min(min_d(l,mid),min_d(mid+1,r));
while(p[l].x+retp[mid].x) --r;
sort(p+l,p+1+r,cmpy);
for(int i=l;ii;--j)
ret=min(ret,dis(p[i],p[j]));
sort(p+l,p+1+r,cmpx);
return ret;
}
inline double min_dis(){
sort(p+1,p+1+n,cmpx);
return min_d(1,n);
}
推荐
http://www.cnblogs.com/xdruid/archive/2012/05/27/CP.html
凸包
时间复杂度:\(O(nlogn)\).
#define N 100005
#define eps 1e-13
struct point{
int x,y;double an;
}a[N],v[N];
int n,u,vn;
inline double sqr(int k){
return (double)(k*k);
}
inline point dec(point x,point y){
return (point){x.x-y.x,x.y-y.y,0.0};
}
inline int mul(point x,point y){
return x.x*y.y-y.x*x.y;
}
inline double dis(point x,point y){
return sqrt(sqr(abs(x.x-y.x))+sqr(abs(x.y-y.y)));
}
inline bool cmp(point x,point y){
if(fabs(x.an-y.an)dis(y,a[1]);
return x.an1&&mul(dec(a[i],v[vn-1]),dec(v[vn],v[vn-1]))>0) --vn;
v[++vn]=a[i];
}
}
旋转卡壳
时间复杂度:\(O(n)\).
#define N 100005
struct point{
int x,y;
}a[N];
int n;
inline point dec(point x,point y){
return (point){x.x-y.x,x.y-y.y};
}
inline int mul(point x,point y){
return x.x*y.y-x.y*y.x;
}
inline double sqr(int k){
return (double)(k*k);
}
inline double dis(point x){
return sqrt(sqr(x.x)+sqr(x.y));
}
inline int Next(int k){
if(++k>n) return 1;
return k;
}
inline double rorate(){
point p;
double di,dia=0.0;
if(n==1) return dia;
for(int i=1,j=2;i<=n;++i){
p=dec(a[Next(i)],a[i]);
while(abs(mul(p,dec(a[j],a[i])))
判断点是否在凸多边形内
inline point dec(point x,point y){
return (point){x.x-y.x,x.y-y.y};
}
inline double mul(point x,point y){
return x.x*y.y-y.x*x.y;
}
inline bool onseg(point p,point a,point b){
if(cmp(mul(dec(a,p),dec(b,p)))) return false;
return cmp(a.x-p.x)*cmp(b.x-p.x)<=0&&cmp(a.y-p.y)*cmp(b.y-p.y)<=0;
}
inline int chk(point p){
int cnt=0,k,d1,d2;
for(int i=1;i<=n;++i){
if(onseg(p,a[i],a[i+1])) return -1;
k=cmp(mul(dec(a[i+1],a[i]),dec(p,a[i])));
d1=cmp(a[i].y-p.y);d2=cmp(a[i+1].y-p.y);
if(k>0&&d1<=0&&d2>0) ++cnt;
if(k<0&&d2<=0&&d1>0) --cnt;
}
if(cnt) return 1;
return 0;
}
半平面交
将半平面按极角排序(靠近法向量方向的半平面更小)
双端队列维护半平面交:顺序加入半平面,当队尾的2个半平面的交点在当前半平面外,删除队尾的半平面;当队头的2个半平面的交点在当前半平面外,删除队头的半平面.
\(P.S.\)形如\(ax+by+c\;\geq\;0\)的方程组的解\(A(x,y)\)满足条件\(\overrightarrow{BA}\;\times\;\overrightarrow{BC}\;\geq\;0(B,C\;\in\;ax+by+c=0)\)(\(ax+by+c<0\)反之)
typedef long double ld;
struct point{
ld x,y;
}p[N];
struct line{
point s,e;ld an;
}a[N],q[N];
int n,m,h,t;
inline point dec(point x,point y){
return (point){x.x-y.x,x.y-y.y};
}
inline ld mult(point x,point y){
return x.x*y.y-x.y*y.x;
}
inline bool cmp(line x,line y){
if(x.an==y.an) return mult(dec(x.e,x.s),dec(y.s,x.s))>0;
return x.an0;
}
inline bool hpi(int k){
for(int i=1;i<=n;++i)
a[i].an=atan2(a[i].e.y-a[i].s.y,a[i].e.x-a[i].s.x);
sort(a+1,a+1+n,cmp);
h=1;t=0;
for(int i=1;i<=n;++i){
while(h=3;
}