bzoj 2829 计算几何

将每张卡四个角的圆心跑graham出正常凸包,再加上一个圆就好了。

要注意先输入的是x,找点时三角函数瞎换就过了。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#define N 40050
#define PI 3.1415926535898
#define exp 1e-8
using namespace std;
int top,tot,n;
double ans;
struct point{
	double x,y;
}p[4*N],s[4*N];
inline double sqr(double x){return x*x;}
inline double dis(point a,point b){
	return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
}
inline double operator *(point a,point b){
	return a.x*b.y-b.x*a.y;
}
inline point operator - (point a,point b){
	return (point){a.x-b.x,a.y-b.y};
}
inline bool operator < (point a,point b){
	return (fabs(a.x-b.x)<exp)?(a.y<b.y):(a.x<b.x);
}
bool cmp(point a,point b){
	if(fabs((a-p[1])*(b-p[1]))<exp)
		return dis(p[1],a)<dis(p[1],b);
	return (a-p[1])*(b-p[1])>0;
}
inline point change(point a,double d,double th){
	return (point){a.x+d*cos(th),a.y+d*sin(th)};
}
void graham(){
	top=0;
	for(int i=1;i<=tot;i++)
		if(p[i]<p[1]) swap(p[i],p[1]);
	sort(p+2,p+tot+1,cmp);
	for(int i=1;i<=tot;i++){
		while(top>1&&(p[i]-s[top-1])*(s[top]-s[top-1])>exp) top--;
		s[++top]=p[i];
	}
}
int main(){
	scanf("%d",&n);
	double a,b,r,xx,yy,th;
	scanf("%lf%lf%lf",&a,&b,&r);
	a-=2*r; b-=2*r;
	for(int i=1;i<=n;i++){
		scanf("%lf%lf%lf",&xx,&yy,&th);
		for(int j=0;j<4;j++){
			point pp=change((point){xx,yy},b/2,th+(j)*(PI/2.0));
			p[++tot]=change(pp,a/2,th+(j+1)*(PI/2.0));
			swap(a,b);
		}
	}
	graham();
	s[top+1]=s[1];
	for(int i=1;i<=top;i++) ans+=dis(s[i],s[i+1]);
	ans+=2*PI*r;
	printf("%0.2lf
",ans);
}


原文地址:https://www.cnblogs.com/Ren-Ivan/p/7746711.html