zoukankan      html  css  js  c++  java
  • 计算几何模板

    二维凸包

    洛谷P2742 【模板】二维凸包 / [USACO5.1]圈奶牛Fencing the Cows

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=10005;
    int n,sta[MAXN],top;
    
    struct Point{
    	double x,y;
    	inline friend Point operator - (Point A,Point B){return (Point){A.x-B.x,A.y-B.y};}
    }a[MAXN];
    inline int cmpd(double A,double B){return fabs(A-B)<1e-8?0:(A>B)*2-1;}
    inline double getdis(Point A,Point B){return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
    typedef Point Vector;
    inline double getcross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
    inline bool cmpy(Point A,Point B){return cmpd(A.y,B.y)==0?cmpd(A.x,B.x)>0:cmpd(A.y,B.y)>0;}
    inline bool cmppr(Point A,Point B){
    	double temp=getcross(A-a[1],B-a[1]);
    	return cmpd(temp,0)==0?cmpd(getdis(a[1],B),getdis(a[1],A))>0:cmpd(temp,0)>0;
    }
    
    int main(){
    	n=read();
    	rin(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);
    	if(n==1){printf("0.00
    ");return 0;}
    	else if(n==2){printf("%.2f",getdis(a[1],a[2]));return 0;}
    	rin(i,2,n) if(cmpy(a[1],a[i])) std::swap(a[1],a[i]);
    	std::sort(a+2,a+n+1,cmppr);
    	top=2,sta[1]=1,sta[2]=2;
    	rin(i,3,n){
    		while(top>2&&cmpd(getcross(a[i]-a[sta[top-1]],a[i]-a[sta[top]]),0)<0) top--;
    		sta[++top]=i;
    	}
    	double c=0;
    	rin(i,2,top) c+=getdis(a[sta[i-1]],a[sta[i]]);c+=getdis(a[sta[top]],a[1]);
    	printf("%.2f",c);
    	return 0;
    }
    

    线段判交

    洛谷P1153 点和线

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #include <iomanip>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=15;
    int n,ans,c[MAXN];
    bool vis[MAXN];
    
    struct Point{
    	double x,y;
    	inline friend Point operator - (Point A,Point B){return (Point){A.x-B.x,A.y-B.y};}
    }a[MAXN],b[MAXN];
    inline int cmpd(double A,double B){return fabs(A-B)<1e-8?0:(A>B)*2-1;}
    typedef Point Vector;
    inline double getdot(Vector A,Vector B){return A.x*B.x+A.y*B.y;}
    inline double getcross(Vector A,Vector B){return A.x*B.y-A.y*B.x;}
    inline bool onseg(Point C,Point A,Point B){return cmpd(getcross(A-C,B-C),0)==0&&cmpd(getdot(A-C,B-C),0)<0;}
    inline bool dointer(Point A,Point B,Point C,Point D){
    	if(std::max(A.x,B.x)<std::min(C.x,D.x)||std::max(C.x,D.x)<std::min(A.x,B.x)||std::max(A.y,B.y)<std::min(C.y,D.y)||std::max(C.y,D.y)<std::min(A.y,B.y)) return 0;
    	double d1=getcross(C-A,B-A)*getcross(B-A,D-A),d2=getcross(A-C,D-C)*getcross(D-C,B-C);
    	if(cmpd(d1,0)<=0||cmpd(d2,0)<=0) return 0;
    	if(cmpd(d1,0)>0&&cmpd(d2,0)>0) return 1;
    	if(cmpd(d1,0)==0) return onseg(C,A,B)|onseg(D,A,B);
    	if(cmpd(d2,0)==0) return onseg(A,C,D)|onseg(B,C,D);
    }
    
    inline bool check(int pos){
    	if(pos<3) return 1;
    	rin(i,2,pos-1) if(dointer(b[i-1],b[i],b[pos-1],b[pos])) return 0;
    	return 1;
    }
    
    void dfs(int pos){
    	if(pos==n+1){b[pos]=b[1];if(check(pos)) ans++;return;}
    	rin(i,2,n){
    		if(vis[i]) continue;
    		b[pos]=a[i];vis[i]=1;//c[pos]=i;
    		if(check(pos)) dfs(pos+1);
    		vis[i]=0;
    	}
    }
    
    int main(){
    	while(1){
    		a[++n].x=read(),a[n].y=read();
    		if(a[n].x==0&&a[n].y==0) break;
    	}
    	b[1]=a[1];vis[1]=1;
    	dfs(2);
    	printf("%d
    ",ans>>1);
    	return 0;
    }
    

    最小圆覆盖

    [BZOJ2823][AHOI2012]信号塔

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=500005;
    int n;
    double r;
    
    struct Point{
    	double x,y;
    }a[MAXN],o;
    inline int dcmp(double A,double B){return fabs(A-B)<1e-6?0:(A>B)*2-1;}
    inline double getdis(Point A,Point B){return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));}
    inline Point getmid(Point A,Point B){return (Point){(A.x+B.x)/2,(A.y+B.y)/2};} 
    inline Point geto(Point A,Point B,Point C){
    	double a=B.x-A.x,b=B.y-A.y,c=C.x-A.x,d=C.y-A.y,e=((B.x*B.x-A.x*A.x)+(B.y*B.y-A.y*A.y))/2,f=((C.x*C.x-A.x*A.x)+(C.y*C.y-A.y*A.y))/2;
    	return (Point){(d*e-b*f)/(a*d-b*c),(c*e-a*f)/(b*c-a*d)};
    }
    
    int main(){
    	n=read();
    	rin(i,1,n) scanf("%lf%lf",&a[i].x,&a[i].y);
    	std::random_shuffle(a+1,a+n+1);
    	o=a[1],r=0;
    	rin(i,2,n){
    		if(dcmp(getdis(a[i],o),r)>0){
    			o=a[i],r=0;
    			rin(j,1,i-1){
    				if(dcmp(getdis(a[j],o),r)>0){
    					o=getmid(a[i],a[j]),r=getdis(a[i],o);
    					rin(k,1,j-1){
    						if(dcmp(getdis(a[k],o),r)>0)
    							o=geto(a[i],a[j],a[k]),r=getdis(a[i],o);
    					}
    				}
    			}
    		}
    	}
    	printf("%.2f %.2f %.2f
    ",o.x,o.y,r);
    	return 0;
    }
    

    半平面交

    [BZOJ3199][Sdoi2013]escape

    题解

    旋转卡壳

    [POJ2187]Beauty Contest

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cmath>
    #include <cctype>
    #include <algorithm>
    #define rin(i,a,b) for(int i=(a);i<=(b);i++)
    #define rec(i,a,b) for(int i=(a);i>=(b);i--)
    #define trav(i,a) for(int i=head[(a)];i;i=e[i].nxt)
    typedef long long LL;
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=50005;
    int n,sta[MAXN],top;
    
    struct Po{
    	LL x,y;
    	inline friend Po operator - (Po A,Po B){return (Po){A.x-B.x,A.y-B.y};}
    }p[MAXN];
    inline LL getdis(Po A,Po B){return (A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y);}
    typedef Po Ve;
    inline LL getcross(Ve A,Ve B){return A.x*B.y-A.y*B.x;}
    inline bool cmppr(Po A,Po B){return getcross(A,B)==0?getdis(A,p[1])<getdis(B,p[1]):getcross(A,B)>0;}
    
    int main(){
    	n=read();
    	rin(i,1,n){
    		p[i].x=read(),p[i].y=read();
    		if(p[i].y<p[1].y||(p[i].y==p[1].y&&p[i].x<p[1].x)) std::swap(p[i],p[1]);
    	}
    	rec(i,n,1) p[i].x-=p[1].x,p[i].y-=p[1].y;
    	std::sort(p+2,p+n+1,cmppr);
    	top=1,sta[1]=1;
    	rin(i,2,n){
    		while(top>1&&getcross(p[sta[top]]-p[sta[top-1]],p[i]-p[sta[top]])<=0) top--;
    		sta[++top]=i;
    	}
    	int ptr1=1,ptr2=2;LL ans=0;
    	for(;ptr1<=top;ptr1++){
    		int nxt1=ptr1%top+1,nxt2=ptr2%top+1;
    		while(getcross(p[sta[nxt1]]-p[sta[ptr1]],p[sta[ptr2]]-p[sta[ptr1]])<getcross(p[sta[nxt1]]-p[sta[ptr1]],p[sta[nxt2]]-p[sta[ptr1]])){
    			ptr2=nxt2;
    			nxt2=ptr2%top+1;
    		}
    		ans=std::max(ans,std::max(getdis(p[sta[ptr1]],p[sta[ptr2]]),getdis(p[sta[nxt1]],p[sta[ptr2]])));
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    c# 设计模式(一) 工厂模式
    微信开发
    一款非常好用的 Windows 服务开发框架,开源项目Topshelf
    基础语法
    C++环境设置
    c++简介
    使用查询分析器和SQLCMD分别登录远程的SQL2005的1434端口
    ps-如何去水印
    html/css/js-横向滚动条的实现
    java中如何给控件设置颜色
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10133229.html
Copyright © 2011-2022 走看看