zoukankan      html  css  js  c++  java
  • 计算几何基础

    凸包算法

    http://poj.org/problem?id=3348

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=5e5+11;
    int n,m;
    struct point{
    	int x,y;
    	point(){}
    	point(int _x,int _y):
    		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 int operator *(const point A,const point B){
    		return A.x*B.y-A.y*B.x;
    	}
    	inline int norm(){
    		return x*x+y*y;
    	}
    }p[N],q[N];
    inline bool operator <(const point A,const point B){
    	int det=(A-p[1])*(B-p[1]);	
    	if(det!=0)return det>0;
    	return (A-p[1]).norm()<(B-p[1]).norm();
    }
    inline void Graham(){
    	int id=1;
    	for(register int i=2;i<=n;++i)
    		if(p[i].x<p[id].x||p[i].x==p[id].x&&p[i].y<p[id].y)
    			swap(p[i],p[id]);
    	sort(p+2,p+n+1);
    	q[++m]=p[1];
    	for(register int i=2;i<=n;++i){
    		while(m>=2&&(p[i]-q[m-1])*(q[m]-q[m-1])>=0)--m;
    		q[++m]=p[i];
    	}
    }
    inline int Area(){
    	int res=0;
    	q[m+1]=q[1];
    	for(register int i=1;i<=m;++i)
    		res+=q[i]*q[i+1];
    	return (res>>1);
    }
    int main(){
    	scanf("%d",&n);
    	for(register int i=1;i<=n;++i)scanf("%d%d",&p[i].x,&p[i].y);
    	Graham();
    	printf("%d
    ",Area()/50);
    	return 0;
    }
    

      

    旋转卡壳

    http://poj.org/problem?id=2187

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=5e5+11;
    int n,m;
    inline int max(int a,int b){
    	return a>b?a:b;
    }
    struct point{
    	int x,y;
    	point(){}
    	point(int _x,int _y):
    		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 int operator *(const point A,const point B){
    		return A.x*B.y-A.y*B.x;
    	}
    	inline int norm()const{
    		return x*x+y*y;
    	}
    }p[N],q[N];
    inline bool operator <(const point A,const point B){
    	int det=(A-p[1])*(B-p[1]);	
    	if(det!=0)return det>0;
    	return (A-p[1]).norm()<(B-p[1]).norm();
    }
    inline void Graham(){
    	int id=1;
    	for(register int i=2;i<=n;++i)
    		if(p[i].x<p[id].x||p[i].x==p[id].x&&p[i].y<p[id].y)
    			swap(p[i],p[id]);
    	sort(p+2,p+n+1);
    	q[++m]=p[1];
    	for(register int i=2;i<=n;++i){
    		while(m>=2&&(p[i]-q[m-1])*(q[m]-q[m-1])>=0)--m;
    		q[++m]=p[i];
    	}
    }
    inline int nxt(int x){
    	return x%m+1;
    }
    inline int area(const point A,const point B,const point C){
    	return (B-A)*(C-A);
    }
    inline int query(){
    	if(m==2)return (q[2]-q[1]).norm();
    	int res=0;
    	for(register int i=1,j=3;i<=m;++i){
    		while(nxt(j)!=i&&area(q[i],q[i+1],q[j])<=area(q[i],q[i+1],q[nxt(j)]))j=nxt(j);
    		res=max(res,(q[i+1]-q[j]).norm());
    		res=max(res,(q[i]-q[j]).norm());
    	}
    	return res;
    }
    int main(){
    	scanf("%d",&n);
    	for(register int i=1;i<=n;++i)scanf("%d%d",&p[i].x,&p[i].y);
    	Graham();
    	printf("%d
    ",query());
    	return 0;
    }
    

      

    BZOJ1069

    http://www.lydsy.com/JudgeOnline/problem.php?id=1069

    先做凸包,再枚举凸包的对角线,对于剩下的两个凸多边形做旋转卡壳

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    typedef double db;
    int n,m;
    const int N=1e6+11;
    struct point{
        db x,y;
        point(){}
        point(db _x,db _y):
            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 db operator*(const point A,const point B){
            return A.x*B.y-A.y*B.x;
        }
        inline db norm()const{
            return x*x+y*y;
        }
    }p[N],q[N];
    inline bool operator<(const point A,const point B){
        db det=(A-p[1])*(B-p[1]);
        if(det!=0)return det>0;
        return (A-p[1]).norm()<(B-p[1]).norm();
    }
    inline void Graham(){
        for(register int i=2;i<=n;++i)
            if(p[i].x<p[1].x||(p[i].x==p[1].x&&p[i].y<p[1].y))
                swap(p[i],p[1]);
        sort(p+2,p+n+1);
        q[++m]=p[1];q[++m]=p[2];
        for(register int i=3;i<=n;++i){
            while(m>1&&(p[i]-q[m-1])*(q[m]-q[m-1])>=0)--m;
            q[++m]=p[i];
        }
    }
    inline int nxt(int x){
        return x%m+1;
    }
    inline db abs(db x){
        return x>=0?x:-x;
    }
    inline db max(db a,db b){
        return a>=b?a:b;
    }
    inline db solve(){
        db ans=0;
        q[m+1]=q[1];
        for(register int i=1,k,l;i<=m;++i){
            l=nxt(nxt(k=nxt(i)));
            for(register int j=nxt(k);j<=m;++j){
                while(nxt(k)!=j&&abs((q[k]-q[i])*(q[j]-q[i]))<=abs((q[nxt(k)]-q[i])*(q[j]-q[i])))k=nxt(k);
                while(nxt(l)!=i&&abs((q[l]-q[i])*(q[j]-q[i]))<=abs((q[nxt(l)]-q[i])*(q[j]-q[i])))l=nxt(l);
                ans=max(ans,1.00*(abs((q[k]-q[i])*(q[j]-q[i]))+abs((q[l]-q[i])*(q[j]-q[i]))));
            }
        }
        return ans*1.00/2.00;
    }
    int main(){
        scanf("%d",&n);
        for(register int i=1;i<=n;++i)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        Graham();
        printf("%.3lf",solve());
        return 0;
    }
    

      

    BZOJ1185

    http://www.lydsy.com/JudgeOnline/problem.php?id=1185

    先做凸包,再枚举凸包的一条边,用旋转卡壳做出该边的平行线,然后用点积求矩形宽的极值(具有单调性)

    复杂度O(n^2)

    #include<cmath>
    #include<algorithm>
    #include<cstdio>
    #define eps 1e-8
    #define inf 1000000000
    using namespace std;
    double ans=1e60;
    int n,top;
    struct P{
        double x,y;
        P(){}
        P(double _x,double _y):x(_x),y(_y){}
        friend inline bool operator<(P a,P b){
            return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;
        }
        friend inline bool operator==(P a,P b){
            return fabs(a.x-b.x)<eps&&fabs(a.y-b.y)<eps;
        }
        friend inline bool operator!=(P a,P b){
            return !(a==b);
        }
        friend inline P operator+(P a,P b){
            return P(a.x+b.x,a.y+b.y);
        }
        friend inline P operator-(P a,P b){
            return P(a.x-b.x,a.y-b.y);
        }
        friend inline double operator*(P a,P b){
            return a.x*b.y-a.y*b.x;
        }
        friend inline P operator*(P a,double b){
            return P(a.x*b,a.y*b);
        }
        friend inline double operator/(P a,P b){
            return a.x*b.x+a.y*b.y;
        }
        friend inline double dis(P a){
            return sqrt(a.x*a.x+a.y*a.y);
        }
    }p[50005],q[50005],t[5];
    inline bool cmp(P a,P b){
        double t=(a-p[1])*(b-p[1]);
        if(fabs(t)<eps)return dis(p[1]-a)-dis(p[1]-b)<0;
        return t>0;
    }
    inline void graham(){
        for(register int i=2;i<=n;++i)
            if(p[i]<p[1])
                swap(p[i],p[1]);
        sort(p+2,p+n+1,cmp);
        q[++top]=p[1];
        for(register int i=2;i<=n;++i){
            while(top>1&&(q[top]-q[top-1])*(p[i]-q[top])<eps)top--;
            q[++top]=p[i];
        }
        q[0]=q[top];
    }
    inline void RC(){
        int l=1,r=1,p=1;
        double L,R,D,H;
        for(register int i=0;i<top;++i){
            D=dis(q[i]-q[i+1]);
            while((q[i+1]-q[i])*(q[p+1]-q[i])-(q[i+1]-q[i])*(q[p]-q[i])>-eps)p=(p+1)%top;
            while((q[i+1]-q[i])/(q[r+1]-q[i])-(q[i+1]-q[i])/(q[r]-q[i])>-eps)r=(r+1)%top;
            if(i==0)l=r;
            while((q[i+1]-q[i])/(q[l+1]-q[i])-(q[i+1]-q[i])/(q[l]-q[i])<eps)l=(l+1)%top;
            L=(q[i+1]-q[i])/(q[l]-q[i])/D,R=(q[i+1]-q[i])/(q[r]-q[i])/D;
            H=(q[i+1]-q[i])*(q[p]-q[i])/D;
            if(H<0)H=-H;
            double tmp=(R-L)*H;
            if(tmp<ans){
                ans=tmp;
                t[0]=q[i]+(q[i+1]-q[i])*(R/D);
                t[1]=t[0]+(q[r]-t[0])*(H/dis(t[0]-q[r]));
                t[2]=t[1]-(t[0]-q[i])*((R-L)/dis(q[i]-t[0]));
                t[3]=t[2]-(t[1]-t[0]);
            }
        }
    }
    int main(){
        scanf("%d",&n);
        for(register int i=1;i<=n;++i)
            scanf("%lf%lf",&p[i].x,&p[i].y);
        graham();
        RC();
        printf("%.5lf
    ",ans);
        int fir=0;
        for(register int i=1;i<=3;++i)
            if(t[i]<t[fir])
                fir=i;
        for(register int i=0;i<=3;++i)
            printf("%.5lf %.5lf
    ",fabs(t[(i+fir)%4].x),fabs(t[(i+fir)%4].y));
        return 0;
    }
    

      

  • 相关阅读:
    UDP协议测试
    openstack ussusi ubuntu 20 centos8 dracut initqueue timeout
    wol linux远程通过数据帧自动开机
    openStack proformancee bottlenecks options optimized
    find 搜索排除搜索目录
    Ipv6
    golang学习笔记 ---日志库 logrus
    golang学习笔记---- 格式化IO
    golang学习笔记 --- struct 嵌套
    golang学习笔记---HTTPS
  • 原文地址:https://www.cnblogs.com/Stump/p/8410883.html
Copyright © 2011-2022 走看看