L. Machining Disc Rotors
题目求切割后圆上两点的最长距离,显然是圆边上的两点,n=100可以使用平方算法,对每个切割圆先判断是否外离内含,然后用余弦定理求出两交点与圆心连线的夹角,按顺时针标记为l,r,表示切割掉的弧,范围【0,2pi】,题目保证切割圆不会交叉,将弧按l排序,遍历求出留下来的弧,一个弧关于圆心的对称弧可以将l,r±pi来求得,最后n方判断对称弧是否与其他弧重叠(若重叠答案为直径),并求弧的左右端点和其他弧左右端点的距离,答案为最大值。
坑点是可能所有的切割圆都外离内含时容易挂掉,并且如果存在优弧则答案就是直径。
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
struct P{
double x,y;
}o1,o;
double l[110],r[110],ln[110],rn[110]; //[0.2pi) clockwise
double RR;
struct L{
double l,r;
bool operator <(L B)const{
return l<B.l;
}
}p[110],p2[110];
inline double cross(P A,P B,P C){
return (A.x-C.x)*(B.y-C.y)-(B.x-C.x)*(A.y-C.y); //CA*CB
}
inline double dis(P A,P B){
return sqrt((A.x-B.x)*(A.x-B.x)+(A.y-B.y)*(A.y-B.y));
}
inline bool ck(double a,double b,double c){
if(b>=a&&c>=a&&c<=b)return true;
if(b<a&&(c<=b||c>=a))return true;
return false;
}
double pi=acos(-1);
inline double f(double x){
if(x>=pi)return x-pi;
return x+pi;
}
inline double xc(double a,double b){
double r=fabs(a-b);
if(r>pi)r=2*pi-r;
return sqrt(2*RR*RR*(1-cos(r)));
}
int n;
inline bool check(int i){
if(p[i].l==-1)return false;
for(int j=1;j<=n;j++){
if(j==i)continue;
if(p[j].l==-1)continue;
if(ck(p[j].l,p[j].r,p[i].l)&&ck(p[j].l,p[j].r,p[i].r))return false;
}
return true;
}
int main(){
int T,TT;
o1.x=1;
scanf("%d",&T);TT=T;
while(T--){
scanf("%d%lf",&n,&RR);
bool fl=false;
double ans=0;
for(int i=1;i<=n;i++){
double rr;
P t;
scanf("%lf%lf%lf",&t.x,&t.y,&rr);
double d=dis(t,o);
if(d>=rr+RR||(rr<RR&&d<=RR-rr)){
p[i].l=-1;
continue;
}
double mid=acos(t.x/d);
if(t.y<0)mid=2*pi-mid;
double re=acos((-rr*rr+RR*RR+d*d)/(2*RR*d));
p[i].l=mid-re;
if(p[i].l<0)p[i].l+=2*pi;
p[i].r=mid+re;
if(p[i].r>=2*pi)p[i].r-=2*pi;
}
int pr,cnt=0,ct=0;
for(int i=1;i<=n;i++){
if(check(i))p2[++ct]=p[i];
}
sort(p2+1,p2+ct+1);
pr=ct;
for(int i=1;i<=ct;i++){
l[++cnt]=p2[pr].r;pr=i;
r[cnt]=p2[i].l;
ln[cnt]=f(l[cnt]);rn[cnt]=f(r[cnt]);
ans=max(xc(l[cnt],r[cnt]),ans);
double len=r[cnt]-l[cnt];
if(len<0)len+=2*pi;
if(len>=pi){
ans=2*RR;
break;
}
for(int j=1;j<cnt;j++){
if(ck(l[j],r[j],ln[cnt])||ck(l[j],r[j],rn[cnt])
||ck(ln[cnt],rn[cnt],l[j])||ck(ln[cnt],rn[cnt],r[j])){
fl=true;ans=2*RR;
break;
}
else {
ans=max(xc(l[cnt],l[j]),ans);
ans=max(xc(l[cnt],r[j]),ans);
ans=max(xc(r[cnt],l[j]),ans);
ans=max(xc(r[cnt],r[j]),ans);
}
}
if(fl)break;
}
if(ans==0)ans=2*RR;
printf("Case #%d: %.10f\n",TT-T,ans);
}
return 0;
}