头文件:
const double eps=1e-8;
const double pi=acos(-1);
inline double P(double x){
return x*x;
}
inline int sign(double x){
return fabs(x)<eps?0:(x>0?1:-1);
}
struct point{
double x,y;
point(double _x=0,double _y=0):x(_x),y(_y){}
friend inline point operator +(const point &a,const point &b){
return point(a.x+b.x,a.y+b.y);
}
friend inline point operator -(const point &a,const point &b){
return point(a.x-b.x,a.y-b.y);
}
friend inline point operator *(const point &a,const double &b){
return point(a.x*b,a.y*b);
}
friend inline point operator /(const point &a,const double &b){
return point(a.x/b,a.y/b);
}
friend inline double operator ^(const point &a,const point &b){
return a.x*b.x+a.y*b.y;
}
friend inline double operator *(const point &a,const point &b){
return a.x*b.y-a.y*b.x;
}
friend inline bool operator <(const point &a,const point &b){
return (a.x==b.x)?a.y<b.y:a.x<b.x;
}
inline void rotate(double t){
double px=x,py=y;
x=px*cos(t)-py*sin(t),y=px*sin(t)+py*cos(t);
}
inline double ang(){
return atan2(y,x);
}
inline double calc(){
return P(x)+P(y);
}
}
struct line{
point s,e;int id;
double rad;
line(){}
line(point x,point y){
s=x,e=y,rad=(y-x).ang();
}
friend inline bool operator <(const line &a,const line &b){
return sign(a.rad-b.rad)?sign(a.rad-b.rad)<0:sign((a.e-a.s)*(b.e-a.s))>0;
}
}
凸包
(POJ3348)
point p[N],q[N];
int n,tot,top;
inline bool comp(const point &a,const point &b){
double k=(a-p[1])*(b-p[1]);
return sign(k)?k>0:(a-p[1]).calc()<(b-p[1]).calc();//关于长度,短的在前
}
void graham(){
for(int i=2;i<=n;i++){
if(p[i]<p[1])swap(p[1],p[i]);
}
sort(p+2,p+n+1,comp);//从2、
q[top=1]=p[1];
for(int i=2;i<=n;i++){
while(top>=2&&sign((p[i]-q[top-1])*(q[top]-q[top-1]))>=0)top--;//相同也弹出
q[++top]=p[i];
}
q[top+1]=q[1];
}
inline int area(){
int res=0;
for(int i=1;i<=top;i++)res+=q[i]*q[i+1];
return res/100;
}
int main(){
n=read();
for(int i=1;i<=n;i++)p[i].x=read(),p[i].y=read();
graham();
cout<<area();
}
旋转卡壳
(POJ2187)
inline int nxt(int x){
return x==m?1:x+1;
}
inline double area(const point &a,const point &b,const point &c){
return (b-a)*(c-a);
}
int main(){
n=read();
for(int i=1;i<=n;i++)p[i].x=read(),p[i].y=read();
graham();
q[m+1]=q[1];
for(int i=1,j=1;i<=m;i++){
while((nxt(j)!=i)&&sign((area(q[i],q[i+1],q[j+1])-area(q[i],q[i+1],q[j])))>=0)j=nxt(j);//注意判边界
ans=max(ans,(q[j]-q[i]).calc());
ans=max(ans,(q[j]-q[i+1]).calc());//似乎不加这句话过不了…,反正加了不会错
}
cout<<ans<<'
';
}
半平面交
(BZOJ2618)
point a[N],b[N];
line p[N],q[N];
inline point insec(const line &a,const line &b){
double t1=(b.s-a.s)*(a.e-a.s),t2=(a.e-a.s)*(b.e-a.s);
double k=(t1)/(t1+t2);
return (b.s+((b.e-b.s)*k));
}
inline double K(int i){
return (q[i].e.y-q[i].s.y)/(q[i].e.x-q[i].s.x);
}
inline double B(int i){
return q[i].s.y-K(i)*q[i].s.x;
}
inline bool comp(const line &a,const line &b,const line &c){
return sign((c.e-c.s)*(insec(a,b)-c.s))<0;
}
int hd,tl,tot,n,m;
int ans[N];
inline void half(){
sort(p+1,p+n+1);
for(int i=1;i<=n;i++){
if(sign(p[i].rad-p[i-1].rad))tot++;
p[tot]=p[i];
}
q[1]=p[1],q[2]=p[2],hd=1,tl=2;
for(int i=3;i<=tot;i++){
while(hd<tl&&comp(q[tl-1],q[tl],p[i]))tl--; //注意先tail后head不能反
while(hd<tl&&comp(q[hd],q[hd+1],p[i]))hd++;
q[++tl]=p[i];
}
while(hd<tl&&comp(q[tl-1],q[tl],q[hd]))tl--;
while(hd<tl&&comp(q[hd],q[hd+1],q[tl]))hd++;
tot=0,q[tl+1]=q[hd];
for(int i=hd;i<=tl;i++)b[++tot]=insec(q[i],q[i+1]);
}
inline double area(){
double res=0;
for(int i=1;i<=tot;i++){
res+=b[i]*b[i%tot+1];
}
return res/2;
}
int main(){
m=read();
for(int i=1;i<=m;i++){
int k=read();
for(int j=1;j<=k;j++)a[j].x=read(),a[j].y=read();
for(int j=1;j<=k;j++)p[++n]=line(a[j],a[j%k+1]);
}
half();
printf("%.3lf",area());
}
经典题目