题目链接:https://vjudge.net/problem/Gym-101955L
题意:n个圆和 圆(0,0,R) 部分相交,求剩余圆的直径
题解:如果剩余部分存在直径的话,那就是2*R,这个怎么判断呢,对于每一个交点,判断他关于(0,0)的对称点是不是在n个圆内,如果都不在的话,那就存在2*R的直径,如果都没有的话,那就是任意两个点的最大距离了
#include <bits/stdc++.h>
using namespace std;
const double PI = acos(-1);
const double eps = 1e-10;
int sgn(double x) {
if(fabs(x) < eps) return 0;
if(x < 0) return -1;
return 1;
}
int n;
double R;
double sqr(double x) {
return x * x;
}
struct Point{
double x, y;
Point(){
}
Point(double x_, double y_) {
x = x_;
y = y_;
}
bool operator == (Point b)const{
return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
}
bool operator < (Point b)const{
return sgn(x-b.x)== 0-sgn(y-b.y)?0:x<b.x;
}
Point operator-(const Point &b)const{
return Point(x-b.x,y-b.y);
}
//2??y
double operator ^(const Point &b)const{
return x*b.y-y*b.x;
}
//μ??y
double operator *(const Point &b)const{
return x*b.x + y*b.y;
}
Point operator +(const Point &b)const{
return Point(x+b.x,y+b.y);
}
Point operator *(const double &k)const{
return Point(x*k,y*k);
}
Point operator /(const double &k)const{
return Point(x/k,y/k);
}
double distance(Point p) {
return sqrt((x - p.x) * (x - p.x) + (y - p.y) * (y - p.y));
}
double len() {
return sqrt(x * x + y * y);
}
Point trunc(double r) {
double l = len();
if(!sgn(l)) return *this;
r /= l;
return Point(x * r, y * r);
}
Point rotleft() {
return Point(-y, x);
}
Point rotright() {
return Point(y, -x);
}
Point rotate(Point p,double angle){
Point v = (*this)-p;
double c = cos(angle), s = sin(angle);
return Point(p.x + v.x*c-v.y*s,p.y + v.x*s + v.y*c);
}
}a[1010];
int len;
struct Line {
Point s, e;
Line(){
}
Line(Point s_, Point e_) {
s = s_;
e = e_;
}
};
struct circle {
Point p;
double r;
circle(){
}
circle(Point p_, double r_) {
r = r_;
p = p_;
}
int relationcircle(circle v) {
double d = p.distance(v.p);
if(sgn(d - r - v.r) > 0) return 5;
if(sgn(d - r - v.r) == 0) return 4;
double l = fabs(r - v.r);
if(sgn(d - r - v.r) < 0 && sgn(d - l) > 0) return 3;
if(sgn(d - l) == 0) return 2;
if(sgn(d - l) < 0) return 1;
}
int getpoint(circle v, Point &p1, Point &p2) {
int rel = relationcircle(v);
if(rel == 1 || rel == 5) return 0;
double d = p.distance(v.p);
double l = (d * d + r * r - v.r * v.r) / (2 * d);
double h = sqrt(r * r - l * l);
Point tmp = p + (v.p - p).trunc(l);
p1 = tmp + ((v.p - p).rotleft().trunc(h));
p2 = tmp + ((v.p - p).rotright().trunc(h));
if(rel == 2 || rel == 4) return 1;
return 2;
}
int relation(Point b){
double dst = b.distance(p);
if(sgn(dst-r) < 0)return 2;
else if(sgn(dst-r)==0)return 1;
return 0;
}
}C[1010];
int main() {
int T, nn = 1;
scanf("%d", &T);
Point p1, p2, pp;
int flag;
double ans;
while(T--) {
scanf("%d %lf", &n, &R);
C[0].p.x = 0;
C[0].p.y = 0;
C[0].r = R;
len = 0;
for(int i = 1; i <= n; i++) {
scanf("%lf %lf %lf", &C[i].p.x, &C[i].p.y, &C[i].r);
flag = C[0].getpoint(C[i], p1, p2);
if(flag == 1) {
len++;
a[len] = p1;
} else if(flag == 2) {
len++;
a[len] = p2;
len++;
a[len] = p1;
}
}
ans = 0;
if(len == 0) {
ans = R * 2;
} else {
for(int i = 1; i <= len; i++) {
for(int j = i + 1; j <= len; j++)
ans = max(ans, a[i].distance(a[j]));
pp = Point(-a[i].x, -a[i].y);
flag = 0;
for(int j = 1; j <= n; j++) {
if(C[j].relation(pp) <= 0) {
flag++;
} else break;
}
if(flag == n) {
// cout << a[i].x << " " << a[i].y << endl;
ans = R * 2;
break;
}
}
}
printf("Case #%d: %.15lf\n", nn++, ans);
}
return 0;
}
本文探讨了一道编程题,通过计算几何的方法解决n个圆与一个中心圆相交后,求剩余部分的最大直径问题。介绍了如何判断剩余部分是否存在直径等于2*R,并提供了详细的代码实现。

被折叠的 条评论
为什么被折叠?



