https://codeforces.com/gym/101955/problem/L
周一牙疼,周二拔智齿,周三周四智齿发炎引起发烧躺尸,4天没训练,完了,要打铁了。
卧槽赛场上写的nlognlogn一直超时,然后偶像说赛后他n^2过了,然后我改成了nlogn还是超时,主要是这个logn是三分的,而且eps要1e-10,本身就几十了,再乘个常数,就超过100了,因为n只有100。。。。果然计算几何还是经验不够,口胡都会,就是不一定写的出来,n^2最后也是5s过的,时限8s,毒瘤卡常题。
就先用余弦定理把可用的弧段全求出来,然后枚举第i段弧和第j段弧,枚举第i段弧的左右端点,如果端点的对面就在第j段弧范围内,那么说明答案就是直径,否则要么第j段弧的左端点距离大一些,要么右端点的距离是第j段弧中离第i段弧枚举的一个端点距离最大,都枚举一下就行了。
#include<bits/stdc++.h>
#define maxl 2010
#define eps 1e-12
using namespace std;
const double pi=acos(-1.0);
inline int sgn(double x)
{
if(x>-eps && x<eps)
return 0;
if(x>0) return 1;
else return -1;
}
struct point
{
double x,y;
point(double a=0,double b=0)
{
x=a;y=b;
}
point operator - (const point &b)const
{
return point(x-b.x,y-b.y);
}
inline void transxy(double sinb,double cosb)
{
double tx=x,ty=y;
x=tx*cosb-ty*sinb;
y=tx*sinb+ty*cosb;
}
inline void tranxy(double b)
{
double tx=x,ty=y;
x=tx*cos(b)-ty*sin(b);
y=tx*sin(b)+ty*cos(b);
}
inline double norm()
{
return sqrt(x*x+y*y);
}
};
inline double det(const point &a,const point &b)
{
return a.x*b.y-a.y*b.x;
}
inline double dot(const point &a,const point &b)
{
return a.x*b.x+a.y*b.y;
}
int n,R,tot,cnt,cas=0;
double ans;
struct cl
{
double hu1,hu2;
}hu[maxl],a[maxl*3];
point res[maxl*3];
inline bool cmp(const cl &a,const cl &b)
{
return a.hu1<b.hu1;
}
inline double rd(double cosval)
{
if(cosval<-1.0)
cosval+=eps;
if(cosval>1.0)
cosval-=eps;
return cosval;
}
inline void prework()
{
scanf("%d%d",&n,&R);
tot=0;
int x,y,r;
double d,t,sita,cosval;
for(int i=1;i<=n;i++)
{
scanf("%d%d%d",&x,&y,&r);
d=sqrt(1.0*x*x+1.0*y*y);
if(d > 1.0*r+R-eps)
continue;
if(d < 1.0*R-r+eps)
continue;
if(y>0)
t=acos(rd(x/d));
else
t=2*pi-acos(rd(x/d));
cosval=(R*R+d*d-r*r)/(2*R*d);
sita=acos(rd(cosval));
++tot;
hu[tot].hu1=t-sita;hu[tot].hu2=t+sita;
if(hu[tot].hu1<0-eps)
{
hu[tot].hu1+=2*pi;
hu[tot].hu2+=2*pi;
}
}
sort(hu+1,hu+1+tot,cmp);
cnt=0;
if(tot==0) return;
for(int i=1;i<tot;i++)
a[cnt++]=cl{hu[i].hu2,hu[i+1].hu1};
a[cnt++]=cl{hu[tot].hu2,hu[1].hu1};
for(int i=0;i<cnt;i++)
{
if(a[i].hu2>2*pi)
{
a[i].hu2-=2*pi;
a[i].hu1-=2*pi;
}
if(a[i].hu2<a[i].hu1)
a[i].hu1-=2*pi;
}
}
inline int nxt(int i)
{
return (i+1)%cnt;
}
inline double dist(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
inline point retp(double sita)
{
return point(cos(sita)*R,sin(sita)*R);
}
inline bool in(double hu,double hu1,double hu2)
{
if(hu>hu1-eps && hu<hu2+eps)
return true;
return false;
}
inline void mainwork()
{
if(cnt==0)
{
ans=2*R;
return;
}
ans=dist(retp(a[0].hu1),retp(a[0].hu2));
int l=0;double t;
for(int i=0;i<cnt;i++)
for(int j=0;j<cnt;j++)
{
if(in(a[i].hu1+pi,a[j].hu1,a[j].hu2))
ans=max(ans,2.0*R);
if(in(a[i].hu1+pi,a[j].hu1+2*pi,a[j].hu2+2*pi))
ans=max(ans,2.0*R);
if(in(a[i].hu2+pi,a[j].hu1,a[j].hu2))
ans=max(ans,2.0*R);
if(in(a[i].hu2+pi,a[j].hu1+2*pi,a[j].hu2+2*pi))
ans=max(ans,2.0*R);
ans=max(ans,dist(retp(a[i].hu1),retp(a[j].hu1)));
ans=max(ans,dist(retp(a[i].hu1),retp(a[j].hu2)));
ans=max(ans,dist(retp(a[i].hu2),retp(a[j].hu1)));
ans=max(ans,dist(retp(a[i].hu2),retp(a[j].hu2)));
}
}
inline void print()
{
++cas;
printf("Case #%d: %.11f\n",cas,ans+eps);
}
int main()
{
//freopen("L.in","r",stdin);
int t;
scanf("%d",&t);
for(int i=1;i<=t;i++)
{
prework();
mainwork();
print();
}
return 0;
}