求凸包周长
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e4+1;
const double eps=1e-8;
struct point
{
double x,y;
point(){}
point(double a,double b)
{
x=a;y=b;
}
point operator -(const point &a)const//向量差
{
return point(x-a.x,y-a.y);
}
double operator ^(const point &a)const//向量叉乘
{
return x*a.y-y*a.x;
}
double operator *(const point &a)const//向量点乘
{
return x*a.x+y*a.y;
}
}p[MAX],b[MAX];
int top,n;
double cross(point a,point b,point c)//叉积(三角形面积*2
{
return (b-a)^(c-a);
}
double dis(point a,point b)//两点距离sqrt(dis)
{
return (a-b)*(a-b);
}
bool cmp(point a,point b)
{
double tmp=cross(p[0],a,b);
if(tmp>eps||(fabs(tmp)<eps&&dis(p[0],a)-dis(p[0],b)>eps)) return 1;
return 0;
}
void graham()
{
int u=0;top=0;
for(int k=1;k<n;k++)
if(p[u].y-p[k].y>eps||(fabs(p[u].y-p[k].y)<eps&&p[u].x-p[k].x>eps))
u=k;
swap(p[u],p[0]);
sort(p+1,p+n,cmp);
if(n>0) {b[0]=p[0];top++;}
if(n>1) {b[1]=p[1];top++;}
if(n<3) return ;
for(int i=2;i<n;i++)
{
while(top>1&&cross(b[top-2],b[top-1],p[i])<eps) top--;
b[top++]=p[i];
}
}
int main()
{
double sum=0;
scanf("%d",&n);
for(int k=0;k<n;k++)
scanf("%lf%lf",&p[k].x,&p[k].y);
graham();
b[top]=b[0];
for(int k=1;k<=top;k++)
sum+=sqrt(dis(b[k],b[k-1]));
printf("%.2f\n",sum);
return 0;
}
求凸包面积
int main()
{
double sum=0;
scanf("%d",&n);
for(int k=0;k<n;k++)
scanf("%lf%lf",&p[k].x,&p[k].y);
graham();
for(int k=1;k<top-1;k++)
sum+=fabs(cross(b[0],b[k],b[k+1]));//凸包中的三角形叉积和
printf("%d\n",(int)(sum/100));
return 0;
}
旋转卡壳 求最远点对
double rotating()
{
double ans=0;
b[top]=b[0];
for(int k=0,i=1;k<=top;k++)
{
while(fabs(cross(b[k],b[i+1],b[k+1]))-fabs(cross(b[k],b[i],b[k+1]))>eps)
i=(i+1)%top;
ans=max(ans,dis(b[i],b[k]));
}
return ans;
}
旋转卡壳 求凸包最小宽度
double rotating()
{
double ans=0x3f3f3f3f;
b[top]=b[0];
for(int k=0,i=1;k<=top;k++)
{
while(fabs(cross(b[k],b[i+1],b[k+1]))-fabs(cross(b[k],b[i],b[k+1]))>eps)
i=(i+1)%top;
ans=min(ans,fabs(cross(b[k],b[k+1],b[i])/sqrt(dis(b[k],b[k+1]))));
}
return ans;
}
旋转卡壳 求平面最大三角形
double rotating()
{
double ans=0;
for(int k=0;k<top;k++)
{
int i=(k+1)%top;
int j=(i+1)%top;
while(i!=k&&j!=k)
{
ans=max(ans,fabs(cross(b[k],b[i],b[j])));
while(fabs(cross(b[k],b[i+1],b[j]))-fabs(cross(b[k],b[i],b[j]))>eps)
i=(i+1)%top;
j=(j+1)%top;
}
}
return ans;
}
旋转卡壳 求两凸包最近距离(min) / 最远距离(max)
#include<stdio.h>
#include<math.h>
#include<algorithm>
using namespace std;
const int MAX=1e4+5;
const double eps=1e-8;
const double INF=1e99;
struct point
{
double x,y;
point(){}
point(double a,double b)
{
x=a;y=b;
}
point operator -(const point &a)const//向量差
{
return point(x-a.x,y-a.y);
}
double operator ^(const point &a)const//向量叉乘
{
return x*a.y-y*a.x;
}
double operator *(const point &a)const//向量点乘
{
return x*a.x+y*a.y;
}
}p[MAX],b1[MAX],b2[MAX];
int top1,top2;
double min(double a,double b)
{
return a-b<-eps?a:b;
}
double cross(point a,point b,point c)//叉积(三角形面积*2
{
return (b-a)^(c-a);
}
double multi(point a,point b,point c)//点积
{
return (b-a)*(c-a);
}
double dis(point a,point b)//两点距离sqrt(dis)
{
return (a-b)*(a-b);
}
double dist(point a,point b,point c)//点线段最短距离a\bc
{
point d;
double t=multi(b,a,c)/dis(b,c);
if(t>-eps&&t-1<eps) d=point(b.x+(c.x-b.x)*t,b.y+(c.y-b.y)*t);
else
{
if(dis(a,b)-dis(a,c)<-eps) d=b;
else d=c;
}
return dis(a,d);
}
//double dist(point a,point b,point c)//sqrt(dis)下
//{
// if(dis(b,c)<eps) return dis(a,c);
// if(multi(b,c,a)<-eps) return dis(a,b);
// if(multi(c,b,a)<-eps) return dis(a,c);
// return fabs(cross(b,c,a)/dis(b,c));
//}
double distence(point a,point b,point c,point d)//两线段距离ab\cd
{
return min(min(dist(a,c,d),dist(b,c,d)),min(dist(c,a,b),dist(d,a,b)));
}
bool cmp(point a,point b)
{
double tmp=cross(p[0],a,b);
if(tmp>eps||(fabs(tmp)<eps&&dis(p[0],a)-dis(p[0],b)>eps)) return 1;
return 0;
}
void graham(point *b,int n,int &top)
{
int u=0;top=0;
for(int k=1;k<n;k++)
if(p[u].y-p[k].y>eps||(fabs(p[u].y-p[k].y)<eps&&p[u].x-p[k].x>eps))
u=k;
swap(p[u],p[0]);
sort(p+1,p+n,cmp);
if(n>0) {b[0]=p[0];top++;}
if(n>1) {b[1]=p[1];top++;}
if(n<3) return ;
for(int i=2;i<n;i++)
{
while(top>1&&cross(b[top-2],b[top-1],p[i])<eps) top--;
b[top++]=p[i];
}
}
double rotating(point *a,int n,point *b,int m)
{
int i1=0,i2=0;
for(int k=0;k<n;k++)
if(a[k].y-a[i1].y<-eps) i1=k;
for(int k=0;k<m;k++)
if(b[k].y-b[i2].y>eps) i2=k;
a[n]=a[0];b[m]=b[0];
double tmp,ans=INF;
for(int k=0;k<n;k++)
{
while((tmp=cross(a[i1+1],b[i2+1],a[i1])-cross(a[i1+1],b[i2],a[i1]))>eps)
i2=(i2+1)%m;
if(tmp<-eps) ans=min(ans,dist(b[i2],a[i1],a[i1+1]));
else ans=min(ans,distence(a[i1],a[i1+1],b[i2],b[i2+1]));
i1=(i1+1)%n;
}
return ans;
}
int main()
{
int n,m;
while(~scanf("%d%d",&n,&m)&&(n||m))
{
for(int k=0;k<n;k++) scanf("%lf%lf",&p[k].x,&p[k].y);
graham(b1,n,top1);
for(int k=0;k<m;k++) scanf("%lf%lf",&p[k].x,&p[k].y);
graham(b2,m,top2);
//G++编译时double 和float 都只能用%f输出,float转为double,C++不影响,比赛时一般以G++为准
printf("%0.5f\n",sqrt(min(rotating(b1,top1,b2,top2),rotating(b2,top2,b1,top1))));
}
return 0;
}