Craters

题目链接:Craters


以前的凸包做法似乎被卡精度了,很神奇,然后换了种写法。

对于一个圆,我们首先先将半径增加10,那么就相当于是把这些圆全部包围的最小长度。

我们把圆等分成5000个点,那么精度损失是很小的,直接求出凸包,然后求面积即可。


AC代码:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include
//#define int long long
using namespace std;
const int N=1e6+10;
const double PI=acos(-1.0);
int n,top,cnt;	double res;
struct node{double x,y;}t[N],st[N];
int cmp(node a,node b){return a.y==b.y?a.x<b.x:a.y<b.y;}
inline double dis(node a,node b){return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));}
inline double corss(node a,node b,node c){return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);}
void Graham(){
	sort(t+1,t+1+cnt,cmp);
	for(int i=1;i<=cnt;i++){
		while(top>=2&&corss(st[top-1],st[top],t[i])<=0)	top--;
		st[++top]=t[i];
	}
	int ttop=top;
	for(int i=cnt-1;i>=1;i--){
		while(top>ttop&&corss(st[top-1],st[top],t[i])<=0)	top--;
		st[++top]=t[i];
	}
	top--;//原点出现首尾两次 
}
signed main(){
	cin>>n; double f=360.0/5000.0/180*PI;
	for(int i=1;i<=n;i++){
		double x,y,r;	cin>>x>>y>>r; r+=10.0;
		for(int j=0;j<5000;j++){
			double c=j*f;
			t[++cnt]={x+r*cos(c),y+r*sin(c)};
		}
	}
	Graham(); res=dis(st[top],st[1]);
	for(int i=2;i<=top;i++)	res+=dis(st[i-1],st[i]);
	printf("%.10lf\n",res);
	return 0;
}

你可能感兴趣的:(计算几何,凸包问题)