题目地址:http://codeforces.com/contest/814/problem/D
题意:就是告诉你有n个圆(跳舞),告诉你圆心和半径,圆两两之间不会有多余一个的交点,所以两圆之间要不是相离要不是内含。有上半场和下半场之分,每个圆只能出现一次,圆不能包含另一个圆,如果一个人跳舞被覆盖奇数次,他的面积就需要被减去,被覆盖偶数次他的面积就会被加上,然后现在问你跳舞合适的最大面积是多少。
思路:贪心,奇数加上,偶数减去
#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <algorithm>
#define N 1010
#define LL long long
#define inf 0x3f3f3f3f
using namespace std;
const double PI = 3.1415926535;
struct node {
double x, y, r;
}yuan[N];
int vis[N];
double cal(node x) {
return x.r*x.r*PI;
}
bool solve(node u, node v){
return (u.x - v.x)*(u.x - v.x) + (u.y - v.y)*(u.y - v.y)<(u.r + v.r)*(u.r + v.r);
}
bool cmp(node a, node b) {
if (a.r == b.r) {
if (a.x == b.x) {
return a.y < b.y;
}
return a.x < b.x;
}
return a.r > b.r;
}
int main() {
//cin.sync_with_stdio(false);
int n;
double sum;
while (cin >> n) {
sum = 0;
for (int i = 0; i < n; i++) {
cin >> yuan[i].x >> yuan[i].y >> yuan[i].r;
}
sort(yuan, yuan + n, cmp);
memset(vis, 0, sizeof(vis));
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (solve(yuan[i], yuan[j])) {
vis[j]++;
}
}
}
for (int i = 0; i < n; i++) {
if (!vis[i]) {
sum += cal(yuan[i]);
}
else if (vis[i] & 1) {
sum += cal(yuan[i]);
}
else {
sum -= cal(yuan[i]);
}
}
printf("%.10lf\n", sum);
}
return 0;
}