小蒟蒻的题解(代码)系列-----凸包入门题目集合

学习过斜率优化的童鞋们应该对凸包都不陌生,这里就不做详细的介绍了
手动上代码 P2742 【模板】二维凸包

#include 
#include 
#include 
#include 
using namespace std;
const int N=100010;
const double eps=1e-8;

struct vector {
	double x,y;
	vector(double x=0,double y=0):x(x),y(y) {};
};
#define point vector
vector operator + (vector a,vector b) {return vector(a.x+b.x,a.y+b.y);}
vector operator - (vector a,vector b) {return vector(a.x-b.x,a.y-b.y);}
vector operator * (vector a,double k) {return vector(a.x*k,a.y* k);}
vector operator / (vector a,double k) {return vector(a.x/k,a.y/k);}
double operator * (vector a,vector b) {return a.x*b.x+a.y*b.y;}
double operator ^ (vector a,vector b) {return a.x*b.y-b.x*a.y;}
vector d[N],hull[N];
bool operator < (point a,point b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
 
int n,m;
double len(vector a) {return sqrt(a.x*a.x+a.y*a.y);}

void get_hull() {
	m=2;
	hull[1]=d[1],hull[2]=d[2];
	for(int i= 3;i<=n;++i) {
		while(m>1&&(((hull[m]-hull[m-1])^(d[i]-hull[m-1]))-eps<0)) --m;
		hull[++m]=d[i];
	}
	int k=m;
	for(int i=n-1;i>=1;--i) {
		while(m>k&&(((hull[m]-hull[m-1])^(d[i]-hull[m-1]))-eps<0)) --m;
		hull[++m]=d[i];
	}
}

int main() {

	cin>>n;
	for(int i=1; i<=n; ++i)
		cin>>d[i].x>>d[i].y;
	sort(d+1,d+n+1) ;
	get_hull();
 	double ans;
	for(int i=1;i<m;++i )
		ans+=len(hull[i]-hull[i+1]);
	printf("%.2lf\n",ans);
  
  	return 0;
}

还有一个板子题poj1113 Wall

#include 
#include 
#include 
#include 
using namespace std;
const int N=100010;
const double eps=1e-8,pi=acos(-1.0);
 
struct vector {
	double x,y;
	vector(double x=0,double y=0):x(x),y(y) {};
};
#define point vector
vector operator + (vector a,vector b) {return vector(a.x+b.x,a.y+b.y);}
vector operator - (vector a,vector b) {return vector(a.x-b.x,a.y-b.y);}
vector operator * (vector a,double k) {return vector(a.x*k,a.y* k);}
vector operator / (vector a,double k) {return vector(a.x/k,a.y/k);}
double operator * (vector a,vector b) {return a.x*b.x+a.y*b.y;}
double operator ^ (vector a,vector b) {return a.x*b.y-b.x*a.y;}
vector d[N],hull[N];
bool operator < (point a,point b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
double l ;
int n,m;
double len(vector a) {return sqrt(a.x*a.x+a.y*a.y);}

void get_hull() {
	m=2;
	hull[1]=d[1],hull[2]=d[2];
	for(int i= 3;i<=n;++i) {
		while(m>1&&(((hull[m]-hull[m-1])^(d[i]-hull[m-1]))-eps<0)) --m;
		hull[++m]=d[i];
	}
	int k=m;
	for(int i=n-1;i>=1;--i) {
		while(m>k&&(((hull[m]-hull[m-1])^(d[i]-hull[m-1]))-eps<0)) --m;
		hull[++m]=d[i];

	}
}

int main() {

	cin>>n>>l;
	for(int i=1; i<=n; ++i)
		cin>>d[i].x>>d[i].y;
	sort(d+1,d+n+1) ;
	get_hull();
	double ans=0;
	hull[m+1]=hull[1];
	for(int i=1;i<=m;++i )
		ans+=len(hull[i]-hull[i+1]);
 	cout<<(int)(ans+2*pi*l+0.5)<<endl;
 	
  	return 0;
}

同样,凸包也可以用来求平面内最远点对(装作不会旋转卡壳)
P1452 Beauty Contest

#include 
#include 
#include 
#include 
using namespace std;
const int N=100010;
const double eps=1e-8;

struct vector {
	double x,y;
	vector(double x=0,double y=0):x(x),y(y) {};
};
#define point vector
vector operator + (vector a,vector b) {return vector(a.x+b.x,a.y+b.y);}
vector operator - (vector a,vector b) {return vector(a.x-b.x,a.y-b.y);}
vector operator * (vector a,double k) {return vector(a.x*k,a.y* k);}
vector operator / (vector a,double k) {return vector(a.x/k,a.y/k);}
double operator * (vector a,vector b) {return a.x*b.x+a.y*b.y;}
double operator ^ (vector a,vector b) {return a.x*b.y-b.x*a.y;}
vector d[N],hull[N];
bool operator < (point a,point b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
 
int n,m;
double len(vector a) {return (a.x*a.x+a.y*a.y);}

void get_hull() {
	m=2;
	hull[1]=d[1],hull[2]=d[2];
	for(int i= 3;i<=n;++i) {
		while(m>1&&(((hull[m]-hull[m-1])^(d[i]-hull[m-1]))-eps<0)) --m;
		hull[++m]=d[i];
	}
	int k=m;
	for(int i=n-1;i>=1;--i) {
		while(m>k&&(((hull[m]-hull[m-1])^(d[i]-hull[m-1]))-eps<0)) --m;
		hull[++m]=d[i];

	}
}

int main() {
	cin>>n;
	for(int i=1; i<=n; ++i)
		cin>>d[i].x>>d[i].y;
	sort(d+1,d+n+1) ;
	get_hull();
	double ans=0;for(int i=1;i<m;++i )
		for(int j=1;j<=m;++j)
			ans=max(len(hull[i]-hull[j]),ans);
	cout<<(int)ans<<endl ;
   
  	return 0;
}

poj 1228 Grandpa’s Estate
题意:意思就是给你一堆点,这堆点本来就是某个凸包上的部分点,问你这堆点是否能确定唯一的凸包
这个题目的题本蒟蒻看了很久很久没有看懂,后来求助某巨佬学习到了什么叫做稳定凸包

还有一个简单题poj3348Cows
这个题目就是求凸包,然后运用叉积求面积,然后看整除多少个五十即可

#include 
#include 
#include 
#include 
using namespace std;
const int N=100010;
const double eps=1e-8;

struct vector {
	double x,y;
	vector(double x=0,double y=0):x(x),y(y) {};
};
#define point vector
vector operator + (vector a,vector b) {return vector(a.x+b.x,a.y+b.y);}
vector operator - (vector a,vector b) {return vector(a.x-b.x,a.y-b.y);}
vector operator * (vector a,double k) {return vector(a.x*k,a.y* k);}
vector operator / (vector a,double k) {return vector(a.x/k,a.y/k);}
double operator * (vector a,vector b) {return a.x*b.x+a.y*b.y;}
double operator ^ (vector a,vector b) {return a.x*b.y-b.x*a.y;}
vector d[N],hull[N];
bool operator < (point a,point b) {return a.x==b.x?a.y<b.y:a.x<b.x;}
 
int n,m;
double len(vector a) {return sqrt(a.x*a.x+a.y*a.y);}

void get_hull() {
	m=2;
	hull[1]=d[1],hull[2]=d[2];
	for(int i= 3;i<=n;++i) {
		while(m>1&&(((hull[m]-hull[m-1])^(d[i]-hull[m-1]))-eps<0)) --m;
		hull[++m]=d[i];
	}
	int k=m;
	for(int i=n-1;i>=1;--i) {
		while(m>k&&(((hull[m]-hull[m-1])^(d[i]-hull[m-1]))-eps<0)) --m;
		hull[++m]=d[i];
	}
}

int main() {

	cin>>n;
	for(int i=1; i<=n; ++i)
		cin>>d[i].x>>d[i].y;
	sort(d+1,d+n+1) ;
	get_hull();
 	double ans;
	hull[m+1]=hull[1];
	for(int i=1;i<=m;++i )
		ans+=fabs(hull[i]^hull[i+1]);
	ans/=2;
	cout<<(int)(ans/50)<<endl ;
  
  	return 0;
}

你可能感兴趣的:(题解,学习,计算几何)