.
题目链接1
题目链接2
2道旋转卡壳算法+凸包模板题
应该说是一个比较标准的算法了,凸包就是排序+单调栈搞一下就好
旋转卡壳就是一个运用了凸包单调性的思想,每次逆时针走一条边,就把对点移动一个
第一题稍微麻烦,需要枚举矩形的一条边,让后找水平方向和垂直方向最远距离,分别用点积和叉积就可以判
第二题直接枚举对角线,让后找左右点到直线最长距离
稍微注意基本运算和函数的实现就可以了,剩下的都是可以现推的
(下一篇半平面交)
//bzoj1185
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define db double
#define eps 1e-7
using namespace std;
struct vec{
db x,y;
vec(){}
vec(db a,db b){ x=a; y=b; }
}; typedef vec point;
inline bool cx(vec a,vec b){ return a.x==b.x?a.y<b.y:a.x<b.x; }
inline int sgn(db x){ return fabs(x)<eps?0:(x>0?1:-1); }
inline db dot(vec a,vec b){ return a.x*b.x+a.y*b.y; }
inline db crs(vec a,vec b){ return a.x*b.y-a.y*b.x; }
inline db len(vec a){ return sqrt(dot(a,a)); }
inline vec operator+(vec a,vec b){ return (vec){a.x+b.x,a.y+b.y}; }
inline vec operator-(vec a,vec b){ return (vec){a.x-b.x,a.y-b.y}; }
inline vec operator*(vec a,db x){ return (vec){a.x*x,a.y*x}; }
inline vec operator/(vec a,db x){ return (vec){a.x/x,a.y/x}; }
inline db dis(point p,point a,point b){
return fabs(crs(p-a,a-b)/len(a-b));
}
inline point glp(point a,point A,point b,point B){
vec u=a-b;
db t=crs(B-b,u)/crs(A-a,B-b);
return a+(A-a)*t;
}
point s[200010],q[200010]; int n,m,t;
inline db disr(point a,point b,point c){
return dot(b-a,c-a);
}
inline db disl(point a,point b,point c){
return dot(a-b,c-a);
}
inline db disu(point a,point b,point c){
return fabs(crs(c-a,a-b));
}
inline db calS(int i,int j,int l,int r){
vec c=s[i+1]-s[i];
return dis(s[j],s[i],s[i+1])*dot(c,s[r]-s[l])/len(c);
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)scanf("%lf %lf",&s[i].x,&s[i].y);
sort(s+1,s+1+n,cx);
for(int i=1;i<=n;++i){
while(1<t && sgn(crs(q[t]-q[t-1],s[i]-q[t-1]))<=0) --t;
q[++t]=s[i];
}
m=t;
for(int i=n-1;i;--i){
while(m<t && sgn(crs(q[t]-q[t-1],s[i]-q[t-1]))<=0) --t;
q[++t]=s[i];
}
--t;
memcpy(s+1,q+1,t*sizeof(vec));
memcpy(s+1+t,q+1,t*sizeof(vec));
memcpy(s+1+t+t,q+1,t*sizeof(vec));
int l,r,j,i=1;
for(r=3;disr(s[i],s[i+1],s[r])<disr(s[i],s[i+1],s[r+1]);++r);
for(l=t;disl(s[i],s[i+1],s[l])<disl(s[i],s[i+1],s[l-1]);--l);
for(j=3;disu(s[i],s[i+1],s[j])<disu(s[i],s[i+1],s[j+1]);++j);
db A=0,B; int ai,aj,al,ar;
A=calS(i,j,l,r); ai=i; al=l; ar=r; aj=j;
for(i=2;i<=t;++i){
for(;disr(s[i],s[i+1],s[r])<disr(s[i],s[i+1],s[r+1]);++r);
for(;disl(s[i],s[i+1],s[l])<disl(s[i],s[i+1],s[l+1]);++l);
for(;disu(s[i],s[i+1],s[j])<disu(s[i],s[i+1],s[j+1]);++j);
B=calS(i,j,l,r);
if(A>B){ A=B; ai=i; al=l; ar=r; aj=j; }
}
vec v=s[ai]-s[ai+1],t(v.y,-v.x);
point a[8];
a[4]=a[0]=glp(s[ai],s[ai+1],s[ar],s[ar]+t);
a[7]=a[3]=glp(s[ai],s[ai+1],s[al],s[al]+t);
a[5]=a[1]=glp(s[aj],s[aj]+v,s[ar],s[ar]+t);
a[6]=a[2]=glp(s[aj],s[aj]+v,s[al],s[al]+t);
int p=0;
for(int i=1;i<4;++i) if(sgn(a[i].y-a[p].y)<0) p=i;
else if(!sgn(a[i].y-a[p].y) && sgn(a[i].x-a[p].x)<=0) p=i;
printf("%.5lf\n",A);
for(int i=0;i<4;++i) printf("%.5lf %.5lf\n",fabs(a[p+i].x),fabs(a[p+i].y));
}
//Bzoj1069:
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define db double
#define eps 1e-7
using namespace std;
struct vec{ db x,y; }; typedef vec point;
inline bool cx(vec a,vec b){ return a.x==b.x?a.y<b.y:a.x<b.x; }
inline int sgn(db x){ return fabs(x)<eps?0:(x>0?1:-1); }
inline db dot(vec a,vec b){ return a.x*b.x+a.y*b.y; }
inline db crs(vec a,vec b){ return a.x*b.y-a.y*b.x; }
inline db len(vec a){ return sqrt(dot(a,a)); }
inline vec operator+(vec a,vec b){ return (vec){a.x+b.x,a.y+b.y}; }
inline vec operator-(vec a,vec b){ return (vec){a.x-b.x,a.y-b.y}; }
inline vec operator*(vec a,db x){ return (vec){a.x*x,a.y*x}; }
inline vec operator/(vec a,db x){ return (vec){a.x/x,a.y/x}; }
inline db dis(point p,point a,point b){
db c=crs(p-a,a-b);
return fabs(c/len(a-b));
}
int n,m,t; point s[2010],q[2010]; db l[2010],r[2010],A;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%lf%lf",&s[i].x,&s[i].y);
sort(s+1,s+1+n,cx);
for(int i=1;i<=n;++i){
while(t>1 && sgn(crs(q[t]-q[t-1],s[i]-q[t-1]))<=0) --t;
q[++t]=s[i];
}
m=t;
for(int i=n-1;i;--i){
while(t>m && sgn(crs(q[t]-q[t-1],s[i]-q[t-1]))<=0) --t;
q[++t]=s[i];
}
--t;
memcpy(s+1,q+1,t*sizeof(vec));
for(int i=1;i<=t;++i){
int j=i+2,k=i+1;
for(;j<t;++j){
while(dis(s[k],s[i],s[j])<=dis(s[k+1],s[i],s[j])) ++k;
l[j]=dis(s[k],s[i],s[j]);
}
j=t-1; k=t;
for(;j>i+1;--j){
while(dis(s[k],s[i],s[j])<=dis(s[k-1],s[i],s[j])) --k;
r[j]=dis(s[k],s[i],s[j]);
}
for(j=i+1;j<t;++j)
A=max(A,len(s[i]-s[j])*(l[j]+r[j]));
}
printf("%.3lf\n",A/2.);
}