计算几何模板

二维凸包

洛谷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\n");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\n",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\n",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\n",ans);
	return 0;
}

posted on 2018-12-18 11:09  ErkkiErkko  阅读(143)  评论(0编辑  收藏  举报