zoukankan      html  css  js  c++  java
  • bzoj 3564 信号增幅仪

    bzoj 3564 信号增幅仪

    • 一道有意义的好题.启发我们善用坐标变换,如在遇到椭圆时使用坐标变换转化为圆来处理.
    • 直接在一个方向上进行伸缩不方便,先将坐标系旋转,使椭圆长轴与 (x) 轴平行,点的坐标变换用旋转公式处理.
    • 坐标系逆时针转过了 ( heta) ,相当于点逆时针转过了 (- heta) .
    • 再沿长轴方向伸缩,将点的横坐标除以 (p) ,椭圆就转化为了圆,求一个最小圆覆盖即可.
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define mp make_pair
    #define pii pair<int,int>
    inline int read()
    {
    	int x=0;
    	bool pos=1;
    	char ch=getchar();
    	for(;!isdigit(ch);ch=getchar())
    		if(ch=='-')
    			pos=0;
    	for(;isdigit(ch);ch=getchar())
    		x=x*10+ch-'0';
    	return pos?x:-x;
    }
    struct v2{
    	double x,y;
    	v2(double x=0,double y=0):x(x),y(y) {}
    	v2 operator + (const v2 &rhs) const
    		{
    			return v2(x+rhs.x,y+rhs.y);
    		}
    	v2 operator / (const double &rhs) const
    		{
    			return v2(x/rhs,y/rhs);
    		}
    	v2 operator - (const v2 &rhs) const
    		{
    			return v2(x-rhs.x,y-rhs.y);
    		}
    	double operator * (const v2 &rhs) const
    		{
    			return x*rhs.y-y*rhs.x;
    		}
    	double modulus()
    		{
    			return sqrt(x*x+y*y);
    		}
    };
    const double PI=acos(-1.0);
    v2 rotate(v2 v,double degree)
    {
    	double rad=degree/180*PI;
    	//v2 res=v2(cos(rad)*v.x-sin(rad)*v.y,sin(rad)*v.x+cos(rad)*v.y);
    	v2 res=v2(v.x*cos(rad)-v.y*sin(rad),v.x*sin(rad)+v.y*cos(rad));
    	return res;
    }
    const int MAXN=5e4+10;
    int n;
    v2 a[MAXN];
    double theta,p;
    void transform()
    {
    	for(int i=1;i<=n;++i)
    		{
    			a[i]=rotate(a[i],theta);
    			a[i].x/=p;
    		}
    }
    const double eps=1e-9;
    int dcmp(double x)
    {
    	return fabs(x)<eps?0:(x>0?1:-1);
    }
    v2 getcentre(v2 a,v2 b,v2 c)
    {
    	v2 centre;
    	double a1=b.x-a.x;
    	double b1=b.y-a.y;
    	double c1=(a1*a1+b1*b1)/2.0;
    	double a2=c.x-a.x;
    	double b2=c.y-a.y;
    	double c2=(a2*a2+b2*b2)/2.0;
    	double d=a1*b2-a2*b1;
    	centre.x=a.x+(c1*b2-c2*b1)/d;
    	centre.y=a.y+(a1*c2-a2*c1)/d;
    	return centre;
    }
    bool incir(v2 centre,double r,v2 p)
    {
    	return dcmp((p-centre).modulus()-r)<=0;
    }
    double MinCircleCover()
    {
    	srand(19260817);
    	random_shuffle(a+1,a+1+n);
    	v2 centre=a[1];
    	double r=0;
    	for(int i=2;i<=n;++i)
    		{
    			if(!incir(centre,r,a[i]))
    				{
    					centre=a[i];
    					r=0;
    					for(int j=1;j<i;++j)
    						{
    							if(!incir(centre,r,a[j]))
    								{
    									centre=(a[i]+a[j])/2.0;
    									r=(a[i]-centre).modulus();
    									for(int k=1;k<j;++k)
    										{
    											if(!incir(centre,r,a[k]))
    												{
    													centre=getcentre(a[i],a[j],a[k]);
    													r=(a[i]-centre).modulus();
    												}
    										}
    								}
    						}
    				}
    		}
    	return r;
    }
    int main()
    {
    	n=read();
    	for(int i=1;i<=n;++i)
    		scanf("%lf%lf",&a[i].x,&a[i].y);
    	scanf("%lf%lf",&theta,&p);
    	theta*=-1;
    	transform();
    	double ans=MinCircleCover();
    	printf("%.3lf
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    ARC和MRC兼容和转换
    ARC下的内存管理
    嵌入式硬件系列一:处理器介绍
    嵌入式Linux GCC常用命令
    一. Linux 下的常用命令
    ARM学习中的必知基本常识
    二叉搜索树详解
    从入门到高手,嵌入式必会技能及学习步骤总结
    史上最全Linux目录结构说明
    排序系列之六:快速排序法进阶
  • 原文地址:https://www.cnblogs.com/jklover/p/10388854.html
Copyright © 2011-2022 走看看