[原创]HDU 3264 Open-air shopping malls [相交圆面积+二分查找]【计算几何】

2016-04-08 22:01:36 Tabris_ 阅读数:566


博客爬取于2020-06-14 22:44:37
以下为正文

版权声明:本文为Tabris原创文章,未经博主允许不得私自转载。
https://blog.csdn.net/qq_33184171/article/details/51100211


题目链接 : http://acm.hdu.edu.cn/showproblem.php?pid=3264

Open-air shopping malls

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2314 Accepted Submission(s): 859

Problem Description
The city of M is a famous shopping city and its open-air shopping malls are extremely attractive. During the tourist seasons, thousands of people crowded into these shopping malls and enjoy the vary-different shopping.

Unfortunately, the climate has changed little by little and now rainy days seriously affected the operation of open-air shopping malls—it’s obvious that nobody will have a good mood when shopping in the rain. In order to change this situation, the manager of these open-air shopping malls would like to build a giant umbrella to solve this problem.

These shopping malls can be considered as different circles. It is guaranteed that these circles will not intersect with each other and no circles will be contained in another one. The giant umbrella is also a circle. Due to some technical reasons, the center of the umbrella must coincide with the center of a shopping mall. Furthermore, a fine survey shows that for any mall, covering half of its area is enough for people to seek shelter from the rain, so the task is to decide the minimum radius of the giant umbrella so that for every shopping mall, the umbrella can cover at least half area of the mall.

Input
The input consists of multiple test cases.
The first line of the input contains one integer T (1<=T<=10), which is the number of test cases.
For each test case, there is one integer N (1<=N<=20) in the first line, representing the number of shopping malls.
The following N lines each contain three integers X,Y,R, representing that the mall has a shape of a circle with radius R and its center is positioned at (X,Y). X and Y are in the range of [-10000,10000] and R is a positive integer less than 2000.

Output
For each test case, output one line contains a real number rounded to 4 decimal places, representing the minimum radius of the giant umbrella that meets the demands.

Sample Input
1
2
0 0 1
2 0 1

Sample Output
2.0822


题目大意 :
就是给你一堆圆 选一个圆的圆心给定一个半径 使得这个圆能够覆盖其他圆面积的一半以上 输出最小的这种圆的面积

解题思路 :
枚举每个点,用二分的方法寻找半径
二分区间为[0,完整覆盖一个圆的半径长度]
然后二分就好
二分判定为 覆盖一个圆面积一半

其中涉及计算相交圆面积
可以先看一看这道题 POJ 2546
详细题解加相交圆面积的算法 可以看这里
http://blog.csdn.net/qq_33184171/article/details/51100090

提示 :
本题数据较少 一个个的枚举即可 不用担心超时的问题
计算几何这种问题相对来说涉及的数学公式非常多
其中反映到编译语言上就会非常复杂
所以多整理模板
参加竞赛时会省很多事


附本题代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# include <iostream>
# include <cstdio>
# include <cmath>
# include <cstring>
# include <algorithm>
# include <cstdlib>
# include <iomanip>
using namespace std;
const double PI = acos(-1.0);
const double EPS = 1e-8;
int n;
struct circle
{
double x,y,r;
} c[10005],ori;
double area[30];
double dis(circle &a,circle &b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

double Area(circle &a)
{
return PI*a.r*a.r;
}

double getcrossarea(circle &a ,circle &b)
{
double d=dis(a,b);

if(d>=a.r+b.r) return 0;

if(d<=fabs(a.r-b.r))
{
double rr=min(a.r,b.r);
return PI*rr*rr;
}

double ang1 = acos((a.r * a.r + d * d - b.r * b.r) / 2. / a.r / d);
double ang2 = acos((b.r * b.r + d * d - a.r * a.r) / 2. / b.r / d);
double ret = ang1 * a.r * a.r + ang2 * b.r * b.r - d * a.r * sin(ang1);
return ret;
}

bool check(circle & ori)
{
for(int i=0;i<n;i++)
{
if (getcrossarea(ori, c[i]) * 2 < PI * c[i].r * c[i].r)
return false;
}
return true;
}

double bin(double l, double r, circle& ori)
{
double mid;
while (fabs(l - r) >= EPS)
{
mid = (l + r) / 2;
ori.r = mid;
if (check(ori))
{
r = mid;
}
else
{
l = mid + EPS;
}
}
return mid;
}

int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=0; i<n; i++)
{
scanf("%lf%lf%lf",&c[i].x,&c[i].y,&c[i].r);
area[i]=Area(c[i]);
}
double ans = 1e10;
for(int i=0; i<n; i++)
{
ori.x = c[i].x;
ori.y = c[i].y;
double right = 0;
for(int j=0; j<n; j++)
{
right = max(right, dis(ori, c[j]) + c[j].r);
}
ans = min(ans, bin(0, right, ori));
}
printf("%.4f\n", ans);
}
return 0;
}