BZOJ 1043: [HAOI2008]下落的圆盘(计算几何)

题目
计算每个圆对另一个圆的覆盖弧度然后取并集就行了。
求弧度用atan2+余弦定理。

AC Code:

#include<bits/stdc++.h>
#define maxn 1005
#define Pi 3.1415926535897932384626433832795
#define inf 0x3f3f3f3f
using namespace std;
double sqr(double a){ return a*a; }

int n;
struct Point{
	double x,y;
	Point(double x=0,double y=0):x(x),y(y){}
	Point operator +(const Point &B)const{ return Point(x+B.x,y+B.y); }
	Point operator -(const Point &B)const{ return Point(x-B.x,y-B.y); }
	double operator*(const Point &B)const{ return x*B.y-y*B.x; }
	
}O[maxn];
double r[maxn];
vector<pair<double,double> >p[maxn];

int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%lf%lf%lf",&r[i],&O[i].x,&O[i].y);
		for(int j=1;j<i;j++){
			double dist = sqrt(sqr(O[i].x-O[j].x)+sqr(O[i].y-O[j].y));
			if(r[j]+dist<=r[i])
				p[j].push_back(make_pair(-Pi,Pi));
			else if(r[i]+r[j]>=dist && r[i]+dist>=r[j]){
				double A = r[i], B = r[j] , C = dist;
				double theta = acos((B*B+C*C-A*A)/(2*B*C)) , alpha = atan2(O[i].y-O[j].y,O[i].x-O[j].x);
				double l = alpha - theta , r = alpha + theta;
				if(l<-Pi) l+=2*Pi,r+=2*Pi;
				if(r>Pi) p[j].push_back(make_pair(l,Pi)),p[j].push_back(make_pair(-Pi,r-2*Pi));
				else p[j].push_back(make_pair(l,r));
			}
		}
	}
	
	double ans = 0;
	for(int i=1;i<=n;i++)
	{
		sort(p[i].begin(),p[i].end());
		int sz= p[i].size();
		double mx = -inf , sum = 2*Pi;
		for(int j=0;j<sz;j++){
			if(mx < p[i][j].first){
				mx = p[i][j].second;
				sum -= mx - p[i][j].first;
			}
			else{
				if(p[i][j].second > mx){
					sum -=p[i][j].second - mx;
					mx = p[i][j].second;
				}
			}
		}
		ans += sum * r[i];
	}
	printf("%.3lf\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值