题目让我们求一个圆心位于的圆(后面都用
表示这个圆的圆心)被
个形状为圆的切割臂切割之后剩余图形(可能是非凸的)的直径,也就是就最远的两个点。很容易想到的是求出所有的交点,枚举任意两个交点之间的距离取最大值,但是还可能存在最远距离为直径的情况。如果一个交点关于点
对称的点没有被切割掉,那么最远的距离就是圆的直径。
求所有的交点很简单,关键在怎么判断最远距离为直径的情况,也就是求是否存在一个交点关于点对称的点不被任何一个机械臂包含。
#include <bits/stdc++.h>
#define fixed(s) fixed<<setprecision(12)<<s
using namespace std;
typedef long long ll;
typedef array<int, 3> Arr;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
const int N = 2e5 + 7;
//浮点数比较
const double eps = 1e-8;
int dcmp(double x) // 符号函数
{
if (fabs(x) < eps) return 0; //为0
if (x < 0) return -1; //负数
return 1; //正数
}
int cmp(double x, double y) // 比较函数
{
if (fabs(x - y) < eps) return 0; //相等
if (x < y) return -1;
return 1;
}
struct Point{
double x, y;
};
Point operator+ (Point a, Point b){
return {a.x + b.x, a.y + b.y};
}
Point operator- (Point a, Point b){
return {a.x - b.x, a.y - b.y};
}
double operator* (Point a, Point b){
return a.x * b.x + a.y * b.y;
}
double operator^ (Point a, Point b){
return a.x * b.y - a.y * b.x;
}
bool operator< (Point a, Point b){
if (a.x == b.x) return a.y < b.y;
return a.x < b.x;
}
bool operator == (Point a, Point b){
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}
//两点的距离
double get_dist(Point a, Point b)
{
double dx = a.x - b.x;
double dy = a.y - b.y;
return sqrt(dx * dx + dy * dy);
}
double cross(Point a, Point b){
return a.x * b.y - a.y * b.x;
}
//计算向量c在向量b的什么方向,也可以计算向量ab和ac构成的平行四边形有向面积
double area(Point a, Point b, Point c)
{
return cross(b - a, c - a);
}
//计算向量a的长度
double get_length(Point a)
{
return sqrt(a * a);
}
//计算向量a和b的夹角
double get_angle(Point a, Point b)
{
return acos(a * b / get_length(a) / get_length(b));
}
struct Circle{
Point c; double r;
Point pnt(double a)
{
return {c.x+cos(a)*r,c.y+sin(a)*r};
}
};
double Angle(Point v)
{
return atan2(v.y,v.x);
}
//求两个圆的交点 也可以求交点个数
void getCircleCircleIntersection(Circle c1,Circle c2,vector<Point> &sol)
{
double d = get_length(c1.c-c2.c);
if(dcmp(d) == 0) return;
if(dcmp(c1.r + c2.r - d) < 0) return;
if(dcmp(fabs(c1.r - c2.r) - d) > 0) return;
double a = Angle(c2.c - c1.c);
double da = acos((c1.r * c1.r + d * d - c2.r * c2.r) / (2 * c1.r * d));
Point p1 = c1.pnt(a - da), p2 = c1.pnt(a + da);
sol.push_back(p1);
if(p1 == p2) return;
sol.push_back(p2);
}
void solve(int id){
int n, R;
cin >> n >> R;
Circle C = {{0, 0}, R};
vector<Circle> p(n);
vector<Point> res; //存交点
for (int i = 0; i < n; i++){
cin >> p[i].c.x >> p[i].c.y >> p[i].r;
}
for (int i = 0; i < n; i++){
getCircleCircleIntersection(C, p[i], res);
}
auto check = [&](Point k){
Point p0 = Point{0, 0} - k; //求出k关于圆心对称的点
for (int i = 0; i < n; i++){
//如果p0被圆p[i]包含则p0到到p[i]的圆心距离小于p[i]半径
if ((p[i].c - p0) * (p[i].c - p0) < p[i].r * p[i].r) return false;
}
return true;
};
int sz = res.size();
for (int i = 0; i < sz; i++){
if (check(res[i])){
cout << "Case #" << id <<": ";
cout << fixed(2.0 * C.r) << '\n';
return;
}
}
double ans = 0;
for (int i = 0; i < sz; i++){
for (int j = i + 1; j < sz; j++){
ans = max(ans, get_dist(res[i], res[j]));
}
}
cout << "Case #" << id <<": ";
cout << fixed(ans) << '\n';
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
cin >> T;
for (int i = 1; i <= T; i++){
solve(i);
}
return 0;
}