BZOJ 1043: [HAOI2008]下落的圆盘

暴力枚举每个圆后面的所有圆
对这些圆每个与当前圆计算覆盖的弧度(有两个半径一个圆心距可以用余弦定理)
把算出来的这些弧度存起来
最后求个区间并,再计算剩余部分弧长
(摘自CreationAugust 的博客)

CODE

#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1005;
const double eps = 1e-10;
const double Pi = acos(-1.0);
inline double sqr(double x) { return x*x; }
struct Point {
	double x, y;
	inline Point(double _x=0, double _y=0): x(_x), y(_y){}
	inline Point operator +(const Point &t)const { return Point(x + t.x, y + t.y); }
	inline Point operator -(const Point &t)const {	return Point(x - t.x, y - t.y); }
	inline double operator *(const Point &t)const { return x*t.y - y*t.x; } //cross
	inline double operator ^(const Point &t)const { return x*t.x + y*t.y; } //dot
	inline double dist(const Point &t)const { return sqrt(sqr(x-t.x) + sqr(y-t.y)); }
	inline double len() { return dist(Point(0, 0)); }
	inline double angle() { return atan2(y, x); }
}O[MAXN];
int n; double r[MAXN];
set< pair<double, double> >S;

inline double calc(double a, double b, double c) {
	return acos((sqr(a)+sqr(b)-sqr(c))/(2*a*b));
}

int main ()
{
	int kase = 1;
	//scanf("%d", &kase);
	while(kase--) {
		scanf("%d", &n);
		for(int i = 1; i <= n; ++i)
			scanf("%lf%lf%lf", &r[i], &O[i].x, &O[i].y);
		double ans = 0;
		for(int i = 1; i <= n; ++i) {
			S.clear();
			for(int j = i+1; j <= n; j++) {
				double Len = O[i].dist(O[j]);
				if(Len + r[i] > r[j] + eps && fabs(Len-r[i]) < r[j]){
					double x = (O[j]-O[i]).angle(), y = calc(r[i], Len, r[j]);
					double R = x + y, L = x - y;
					if(L < -Pi) L += 2*Pi, R += 2*Pi;
					if(R > Pi) S.insert(make_pair(L, Pi)), S.insert(make_pair(-Pi, R-2*Pi));
					else S.insert(make_pair(L, R));
				}
				else if(Len + r[i] <= r[j] + eps)
					S.insert(make_pair(-Pi, Pi));
			}
			set< pair<double, double> >::iterator it = S.begin();
			double R = -Pi, sum = 0;
			while(it != S.end()) {
				if((*it).first > R) sum += (*it).first - R;
				R = max(R, (*it).second); ++it;
			}
			sum += Pi - R;
			ans += sum*r[i];
		}
		printf("%.3f
", ans);
	}
}
原文地址:https://www.cnblogs.com/Orz-IE/p/12039297.html