• BZOJ 2823: [AHOI2012]信号塔


    BZOJ 2823: [AHOI2012]信号塔

    标签(空格分隔): OI-BZOJ OI-最小圆覆盖


    Time Limit: 10 Sec
    Memory Limit: 128 MB


    Description

    在野外训练中,为了确保每位参加集训的成员安全,实时的掌握和收集周边环境和队员信息非常重要,集训队采用的方式是在训练所在地散布N个小型传感器来收集并传递信息,这些传感器只与设在集训地中的信号塔进行通信,信号塔接收信号的覆盖范围是圆形,可以接收到所有分布在该集训区域内所有N个小型传感器(包括在该圆形的边上)发出的信号。信号塔的功率与信号塔接收范围半径的大小成正比,因为是野外训练,只能使用事先储备好的蓄电设备,因此在可以收集所有传感器信息的基础上,还应使得信号塔的功率最小。小龙帮助教官确定了一种信号塔设置的方案,既可以收集到所有N个传感器的信号,又可以保证这个信号塔的功率是最小的。同学们,你们知道,这个信号塔的信号收集半径有多大,它应该设置在何处吗?
    Input

    共N+1行,第一行为正整数N(1≤N≤1000000),表示队员个数。接下来
    N行,每行两个实数用空格分开,分别是第i个队员的坐标X

    Output

    一行,共三个实数(中间用空格隔开),分别是信号塔的坐标,和信号塔 覆盖的半径。 (注:队员是否在边界上的判断应符合他到圆心的距离与信号塔接收半径之差的绝对值小于10^-6
    Sample Input

    5

    1.200 1.200

    2.400 2.400

    3.800 4.500

    2.500 3.100

    3.900 1.300

    Sample Output

    2.50 2.85 2.10

    HINT

    1≤N≤500000


    Solution####

    最小圆覆盖随机增量法


    Code####

    #include<stdio.h>
    #include<math.h>
    #include<algorithm>
    using namespace std;
    const double eps=1e-6;
    struct Point
    {
        double x,y;
    };
    double distan(Point p1,Point p2)
    {
    	return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));  
    }
    int n;
    Point a[1000005],o;
    double r;
    void circum(Point p1,Point p2,Point p3)
    {
    	double a=2*(p2.x-p1.x),b=2*(p2.y-p1.y),c=p2.x*p2.x+p2.y*p2.y-p1.x*p1.x-p1.y*p1.y,
    		   d=2*(p3.x-p1.x),e=2*(p3.y-p1.y),f=p3.x*p3.x+p3.y*p3.y-p1.x*p1.x-p1.y*p1.y;
    	o.x=(b*f-e*c)/(b*d-e*a);
    	o.y=(d*c-a*f)/(b*d-e*a);
    	r=distan(p1,o);
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        	scanf("%lf%lf",&a[i].x,&a[i].y);
        random_shuffle(&a[1],&a[n+1]);
        o=a[1],r=0;
        for(int i=2;i<=n;i++)  
     		if(distan(o,a[i])>r+eps)   
     		  {
        	   o=a[i];r=0;  
               for(int j=1;j<=i-1;j++) 
         		  if(distan(o,a[j])>r+eps)   
         			{
             		 o.x=(a[i].x+a[j].x)/2;  
             		 o.y=(a[i].y+a[j].y)/2;  
             		 r=distan(o,a[j]); 
             		 for(int k=1;k<=j-1;k++)
             			if(distan(o,a[k])>r+eps)
                		  circum(a[i],a[j],a[k]);
         			}  
     		  }
        printf("%.2lf %.2lf %.2lf
    ",o.x,o.y,r);
        return 0;
    }
    
  • 相关阅读:
    Java 类加载机制详解
    设置菜单栏中和地址栏对应的活动项高亮
    相交链表
    二叉树的最大深度 递归
    买卖股票的最佳时机 一次遍历
    对称二叉树 递归&迭代
    二叉树的中序遍历 --采用递归
    最大子序和 动态规划
    前K个高频单词 字符型 用Hash表+Collections排序 + 优先队列
    加一 (运用取余数)
  • 原文地址:https://www.cnblogs.com/wuyuhan/p/5295502.html
Copyright © 2020-2023  润新知