zoukankan      html  css  js  c++  java
  • [BZOJ 3564] [SHOI2014] 信号增幅仪 【最小圆覆盖】

    题目链接:BZOJ - 3564

    题目分析

    求最小椭圆覆盖,题目给定了椭圆的长轴与 x 轴正方向的夹角,给定了椭圆长轴与短轴的比值。

    那么先将所有点旋转一个角度,使椭圆长轴与 x 轴平行,再将所有点的 x 坐标除以长轴与短轴的比值,然后就直接做最小圆覆盖了。

    随机增量法,一定别忘了 random_shuffle 。

    代码

    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #include <algorithm>
    
    using namespace std;
    
    #define PI 3.14159265358979323846
    #define Vector Point
    
    typedef double LF;
    
    const int MaxN = 50000 + 5;
    
    const LF Eps = 1e-9;
    
    int n;
    
    LF Alpha, SinA, CosA;
    
    struct Point
    {
    	LF x, y;
    	
    	Point() {}
    	Point(LF a, LF b)
    	{
    		x = a; y = b;
    	}
    	
    	void Rotate(LF SinA, LF CosA)
    	{
    		LF tx, ty;
    		tx = CosA * x - SinA * y;
    		ty = SinA * x + CosA * y;
    		x = tx; y = ty;
    	}
    } P[MaxN];
    
    inline LF Sqr(LF x) {return x * x;}
    
    inline LF Dis(Point p1, Point p2)
    {
    	return sqrt(Sqr(p1.x - p2.x) + Sqr(p1.y - p2.y));
    }
    
    Point operator + (Point p1, Point p2) {return Point(p1.x + p2.x, p1.y + p2.y);}
    Point operator - (Point p1, Point p2) {return Point(p1.x - p2.x, p1.y - p2.y);}
    Point operator * (Point p, LF t) {return Point(p.x * t, p.y * t);}
    Point operator / (Point p, LF t) {return Point(p.x / t, p.y / t);}
      
    struct Line
    {
    	Point p;
    	Vector v;
    	
    	Line() {}
    	Line(Point p1, Point p2)
    	{
    		p = p1;
    		v = p2 - p1;
    	}
    } L1, L2; 
    
    struct Circle
    {
    	Point o;
    	LF r;
    	
    	bool InCircle(Point p)
    	{
    		return Dis(o, p) <= r + Eps;
    	}
    } C;
    
    inline LF Cross(Vector v1, Vector v2)
    {
    	return v1.x * v2.y - v2.x * v1.y;
    }
    
    Point Intersection(Line l1, Line l2)
    {
    	Vector u = l2.p - l1.p;
    	LF t = Cross(u, l2.v) / Cross(l1.v, l2.v);
    	return l1.p + (l1.v * t); 
    }
    
    Vector Turn90(Vector v)
    {
    	return Vector(-v.y, v.x);
    }
    
    Line Verticle(Point p1, Point p2)
    {
    	Line ret;
    	ret.p = (p1 + p2) / 2.0;
    	ret.v = Turn90(p2 - p1);
    	return ret;
    }
    
    int main()
    {
    	srand(51405102);
    	scanf("%d", &n);
    	int a, b;
    	for (int i = 1; i <= n; ++i) 
    	{
    		scanf("%d%d", &a, &b);
    		P[i] = Point((LF)a, (LF)b);
    	}
    	random_shuffle(P + 1, P + n + 1);
    	int ad, p;
    	scanf("%d", &ad);
    	Alpha = (LF)(-ad) / (LF)180 * PI;
    	SinA = sin(Alpha); CosA = cos(Alpha);
    	scanf("%d", &p);
    	for (int i = 1; i <= n; ++i)
    	{
    		P[i].Rotate(SinA, CosA);
    		P[i].x /= (LF)p;
    	}
    	C.o = P[1]; C.r = 0;
    	for (int i = 1; i <= n; ++i)
    	{
    		if (C.InCircle(P[i])) continue;
    		C.o = P[i]; C.r = 0;
    		for (int j = 1; j < i; ++j)
    		{
    			if (C.InCircle(P[j])) continue;
    			C.o = (P[i] + P[j]) / 2.0;
    			C.r = Dis(C.o, P[j]);
    			for (int k = 1; k < j; ++k)
    			{
    				if (C.InCircle(P[k])) continue;
    				L1 = Verticle(P[i], P[k]);
    				L2 = Verticle(P[j], P[k]);
    				C.o = Intersection(L1, L2);
    				C.r = Dis(C.o, P[k]);
    			}
    		}
    	}
    	printf("%.3lf
    ", C.r);
    	return 0;
    }
    

      

  • 相关阅读:
    Mac OS X系统下的Android环境变量配置
    mac 终端 常用命令
    如何在mac本上安装android sdk
    让浏览器支持Webp
    ngCordova安装配置使用教程
    js中const,var,let区别
    avaScript技术面试时要小心的三个问题
    视频H5のVideo标签在微信里的坑和技巧
    Git 忽略一些文件不加入版本控制
    "The /usr/local directory is not writable."解决方法
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4428848.html
Copyright © 2011-2022 走看看