2018沈阳gym101955 L Machining Disc Rotors

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;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值