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

      

  • 相关阅读:
    POJ 1703 Find them, Catch them
    POJ 2236 Wireless Network
    POJ 2010 Moo University
    POJ 2184 Cow Exhibition
    POJ 3280 Cheapest Palindrome
    POJ 3009 Curling 2.0
    POJ 3669 Meteor Shower
    POJ 2718 Smallest Difference
    POJ 3187 Backward Digit Sums
    POJ 3050 Hopscotch
  • 原文地址:https://www.cnblogs.com/JoeFan/p/4428848.html
Copyright © 2011-2022 走看看