旋转卡壳的题没什么难度,主要是熟练运用模板和熟悉算法。
A - Beauty Contest
求凸多边形直径模板题,由于都是整数点,极角排序如果用角度而非叉积的话很有可能被卡精度(哭),所以计算几何题尽量还是整数运算吧。。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<cmath>
using namespace std;
const int maxn=50005;
const double eps=1e-6;
int sgn(double x)
{
if(fabs(x)<eps)return 0;
if(x>0)return 1;
return -1;
}
struct Point
{
int x,y;
Point(int _x,int _y):x(_x),y(_y){}
Point(){}
Point operator-(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
double operator *(const Point &b)const
{
return x*b.x+y*b.y;
}
double operator ^(const Point &b)const
{
return x*b.y-y*b.x;
}
};
Point p[maxn];
double dis(Point a)
{
return sqrt(0.0+a.x*a.x+a.y*a.y);
}
int dis2(Point a)
{
return a.x*a.x+a.y*a.y;
}
int xmult(Point a,Point b,Point c)
{
return (a-c)^(b-c);
}
bool cmp(Point a,Point b)
{
int tmp=xmult(a,b,p[1]);
if(tmp>0||tmp==0&&dis2(a-p[1])<dis2(b-p[1]))return true;
return false;
}
Point ch[maxn];
int N;
int solve()
{
int n=N;
ch[1]=p[1],ch[2]=p[2];
int top=2;
for(int i=3;i<=n;i++)
{
while(top-1>=1&&((p[i]-ch[top-1])^(ch[top]-ch[top-1]))>=0)top--;
ch[++top]=p[i];
}
return top;
}
void solve2(int num)
{
int p=2;
int ans=0;
ch[num+1]=ch[1];
for(int i=1;i<=num;i++)
{
while(xmult(ch[i+1],ch[p+1],ch[i])>xmult(ch[i+1],ch[p],ch[i]))p=p%num+1;
ans=max(ans,dis2(ch[i]-ch[p]));
ans=max(ans,dis2(ch[i+1]-ch[p]));
}
cout<<ans<<endl;
}
int main()
{
scanf("%d",&N);
int x,y;
for(int i=1;i<=N;i++)
{
scanf("%d %d",&x,&y);
p[i]=Point(x,y);
if(y<p[1].y||y==p[1].y&&x<p[1].x)
swap(p[1],p[i]);
}
if(N==2)
{
cout<<dis2(p[2]-p[1])<<endl;
return 0;
}
sort(p+2,p+N+1,cmp);
int num=solve();
/*int ans=0;
for(int i=1;i<=num;i++)
for(int j=i+1;j<=num;j++)
ans=max(ans,dis2(ch[i]-ch[j]));
cout<<ans<<endl;*/
if(num==2)
printf("%d\n",dis2(ch[2]-ch[1]));
else solve2(num);
}
B - Bridge Across Islands
求凸多边形间最小距离。
没啥坑
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
using namespace std;
const int maxn=10005;
const double eps=1e-9;
int sgn(double x)
{
if(fabs(x)<eps)return 0;
if(x>0)return 1;
return -1;
}
struct Point
{
double x,y;
Point(){}
Point(double sx,double sy):x(sx),y(sy){}
double operator *(const Point &b)const
{
return x*b.x+y*b.y;
}
double operator^(const Point &b)const
{
return x*b.y-y*b.x;
}
Point operator-(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
};
Point p1[maxn],p2[maxn];
Point ch1[maxn],ch2[maxn];
int N,M;
Point o;
double dis(Point a)
{
return sqrt(a.x*a.x+a.y*a.y);
}
bool cmp(Point a,Point b)
{
double tmp1=atan2(a.y-o.y,a.x-o.x);
double tmp2=atan2(b.y-o.y,b.x-o.x);
if(sgn(tmp1-tmp2)!=0)return sgn(tmp1-tmp2)<0;
return sgn(dis(a-o)-dis(b-o))<0;
}
int graham(int num,Point *p,Point *ch)
{
for(int i=2;i<=num;i++)
if(sgn(p[i].y-p[1].y)<0||sgn(p[i].y-p[1].y)==0&&sgn(p[i].x-p[1].x)<0)
swap(p[i],p[1]);
o=p[1];
sort(p+2,p+num+1,cmp);
ch[1]=p[1],ch[2]=p[2],ch[3]=p[3];
int top=3;
for(int i=4;i<=num;i++)
{
while(top-1>=1&&sgn((p[i]-ch[top-1])^(ch[top]-ch[top-1]))>=0)top--;
ch[++top]=p[i];
}
return top;
}
typedef const Point CP;
double disptoseg(CP &p,CP &l1,CP &l2)
{
Point t=p;
t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
if(sgn(((l1-p)^(t-p))*((l2-p)^(t-p)))>0)
return dis(p-l1)<dis(p-l2)?dis(p-l1):dis(p-l2);
return fabs(((p-l2)^(l1-l2)))/dis(l1-l2);
}
double dissegtoseg(CP &l1a,CP &l1b,CP &l2a,CP &l2b)
{
return min(min(disptoseg(l1a,l2a,l2b),disptoseg(l1b,l2a,l2b)),min(disptoseg(l2a,l1a,l1b),disptoseg(l2b,l1a,l1b)));
}
double solve(Point *a,int anum,Point *b,int bnum)
{
int i;
double tmp,res=1e10;
a[anum+1]=a[1],b[bnum+1]=b[1];
int p,q;
double ymin=1e5,ymax=-1e5;
for(i=1;i<=anum;i++)
{
if(a[i].y<ymin)
{
ymin=a[i].y;
p=i;
}
}
for(i=1;i<=bnum;i++)
{
if(b[i].y>ymax)
{
ymax=b[i].y;
q=i;
}
}
//cout<<p<<' '<<q<<endl;
for(i=1;i<=anum;i++)
{
while(sgn((tmp=((a[p+1]-a[p])^(b[q+1]-a[p]))-((a[p+1]-a[p])^(b[q]-a[p]))))>0)
q=q%bnum+1;
if(sgn(tmp)<0)res=min(res,disptoseg(b[q],a[p],a[p+1]));
else res=min(res,dissegtoseg(a[p],a[p+1],b[q],b[q+1]));
p=p%anum+1;
//cout<<res<<endl;
}
return res;
}
int main()
{
//freopen("input.txt","r",stdin);
while(~scanf("%d %d",&N,&M))
{
if(N==0&&M==0)break;
double x,y;
for(int i=N;i>=1;i--)
{
scanf("%lf %lf",&x,&y);
p1[i]=Point(x,y);
}
for(int i=M;i>=1;i--)
{
scanf("%lf %lf",&x,&y);
p2[i]=Point(x,y);
}
int p1num=graham(N,p1,ch1);
int p2num=graham(M,p2,ch2);
//cout<<p1num<<endl;
//cout<<p2num<<endl;
double tmp=solve(ch1,p1num,ch2,p2num);
printf("%.5f\n",min(tmp,solve(ch2,p2num,ch1,p1num)));
}
return 0;
}
C - Triangle
我不太理解它这个做法的正确性。。但十分有道理。。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
using namespace std;
const double eps=1e-9;
const int maxn=50005;
int sgn(double x)
{
if(fabs(x)<eps)return 0;
if(x>0)return 1;
return -1;
}
struct Point
{
int x,y;
Point() {}
Point(int sx,int sy):x(sx),y(sy) {}
double operator*(const Point &b)const
{
return x*b.x+y*b.y;
}
double operator^(const Point &b)const
{
return x*b.y-y*b.x;
}
Point operator-(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
};
Point p[maxn];
Point ch[maxn];
int n;
long long dis2(Point a)
{
return a.x*a.x+a.y*a.y;
}
bool cmp(Point a,Point b)
{
double tmp1=atan2(a.y-p[1].y,a.x-p[1].x);
double tmp2=atan2(b.y-p[1].y,b.x-p[1].x);
if(sgn(tmp1-tmp2)!=0)return sgn(tmp1-tmp2)<0;
return dis2(a-p[1])-dis2(b-p[1])<0;
}
int xmult(Point a,Point b,Point c)
{
return (a-c)^(b-c);
}
int top;
void graham()
{
sort(p+2,p+n+1,cmp);
ch[1]=p[1],ch[2]=p[2],ch[3]=p[3];
top=3;
for(int i=4; i<=n; i++)
{
while(top-1>=1&&xmult(p[i],ch[top],ch[top-1])>=0)top--;
ch[++top]=p[i];
}
}
void solve()
{
int p=2,q=3;
int ans=0;
ch[top+1]=ch[1];
for(int i=1; i<=top; i++)
{
while(xmult(ch[p],ch[q+1],ch[i])>xmult(ch[p],ch[q],ch[i]))q=q%top+1;
ans=max(ans,xmult(ch[p],ch[q],ch[i]));
while(xmult(ch[p+1],ch[q],ch[i])>xmult(ch[p],ch[q],ch[i]))p=p%top+1;
ans=max(ans,xmult(ch[p],ch[q],ch[i]));
}
printf("%.2f\n",1.0*ans/2);
}
int main()
{
//freopen("input.txt","r",stdin);
while(~scanf("%d",&n)&&n!=-1)
{
int x,y;
for(int i=1; i<=n; i++)
{
scanf("%d %d",&x,&y);
p[i]=Point(x,y);
if(y<p[1].y||y==p[1].y&&x<p[1].x)
swap(p[1],p[i]);
}
if(n<3)puts("0.00");
else graham(),solve();
}
return 0;
}
D - Smallest Bounding Rectangle
最小外接矩形面积
讲道理没啥坑,主要我凸包写搓了,wa了10几发。。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stdio.h>
#include<math.h>
using namespace std;
const double eps=1e-8;
const int maxn=1005;
int sgn(double x)
{
if(fabs(x)<eps)return 0;
if(x>0)return 1;
return -1;
}
struct Point
{
double x,y;
Point(){}
Point(double sx,double sy):x(sx),y(sy){}
double operator*(const Point &b)const
{
return x*b.x+y*b.y;
}
double operator^(const Point &b)const
{
return x*b.y-y*b.x;
}
Point operator-(const Point &b)const
{
return Point(x-b.x,y-b.y);
}
};
Point p[maxn];
Point ch[maxn];
double dis(Point a)
{
return sqrt(a.x*a.x+a.y*a.y);
}
bool cmp(Point a,Point b)
{
double tmp1=atan2(a.y-p[1].y,a.x-p[1].x);
double tmp2=atan2(b.y-p[1].y,b.x-p[1].x);
if(sgn(tmp1-tmp2)!=0)return sgn(tmp1-tmp2)<0;
return sgn(dis(a-p[1])-dis(b-p[1]))<0;
}
double xmult(Point a,Point b,Point c)
{
return (a-c)^(b-c);
}
double dot(Point a,Point b,Point c)
{
return (a-c)*(b-c);
}
int n;
int graham()
{
sort(p+2,p+n+1,cmp);
ch[1]=p[1],ch[2]=p[2];
int top=2;
for(int i=3;i<=n;i++)
{
while(top-1>=1&&sgn(xmult(p[i],ch[top],ch[top-1]))>=0)top--;
ch[++top]=p[i];
}
return top;
}
double solve(int num)
{
int r=2,q=2,p;
double res=1e10;
ch[num+1]=ch[1];
for(int i=1;i<=num;i++)
{
while(sgn(xmult(ch[i+1],ch[r+1],ch[i])-xmult(ch[i+1],ch[r],ch[i]))>0)r=r%num+1;
while(sgn(dot(ch[i+1],ch[q+1],ch[i])-dot(ch[i+1],ch[q],ch[i]))>0)q=q%num+1;
if(i==1)p=q;
while(sgn(dot(ch[i+1],ch[p+1],ch[i])-dot(ch[i+1],ch[p],ch[i]))<=0)p=p%num+1;
double a=xmult(ch[i+1],ch[r],ch[i]);
double b=dot(ch[i+1],ch[q],ch[i])-dot(ch[i+1],ch[p],ch[i]);
double c=dot(ch[i+1],ch[i+1],ch[i]);
res=min(res,a*b/c);
}
return res;
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
while(~scanf("%d",&n)&&n)
{
double x,y;
for(int i=1;i<=n;i++)
{
scanf("%lf %lf",&x,&y);
p[i]=Point(x,y);
if(sgn(y-p[1].y)<0||sgn(y-p[1].y)==0&&sgn(x-p[1].x)<0)
swap(p[1],p[i]);
}
if(n<=2){puts("0.0000");continue;}
int num=graham();
//cout<<num<<endl;
if(num<=2){puts("0.0000");continue;}
double ans=solve(num);
printf("%.4lf\n",ans);
}
return 0;
}