zoukankan      html  css  js  c++  java
  • CodeForces

    题目

    题目链接

    简单的说,就是作一个圆包含所有的点且与x轴相切,求圆的最小半径

    方法一

    分析:求最小,对半径而言肯定满足单调性,很容易想到二分。我们二分半径,然后由于固定了与X轴相切,我们对于每一个点,就可以算出这个点在圆上的时候圆与x轴相交的距离(其实就是圆心的x轴的范围)。然后对每个点都可以求一个圆心的横坐标区间,如果所有的区间有相交区域,则该半径满足条件,否则不满足。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cmath>
     4 #include<algorithm>
     5 using namespace std;
     6 
     7 const int maxn = 100000 + 10;
     8 const double esp = 1e-6;
     9 struct Piont
    10 {
    11     double x, y;
    12 }p[maxn];
    13 int n;
    14 
    15 bool judge(double r)
    16 {
    17     double ml = -1e15, mr = 1e15;
    18     for (int i = 0; i < n; i++)
    19     {
    20         if (p[i].y > 2 * r)  return false;        //大于2倍半径的,肯定不行
    21         double tmp = sqrt(2 * p[i].y * r - p[i].y * p[i].y);
    22         if (p[i].x - tmp > ml)  ml = p[i].x - tmp;
    23         if (p[i].x + tmp < mr)  mr = p[i].x + tmp;
    24     }
    25     return ml <= mr;                //所有区间必须要有交点
    26 }
    27 
    28 int main()
    29 {
    30     while (scanf("%d", &n) == 1)
    31     {
    32         int flag1 = 0, flag2 = 0;
    33         for (int i = 0; i < n; i++)
    34         {
    35             scanf("%lf%lf", &p[i].x, &p[i].y);
    36             if (p[i].y > 0)  flag1 = 1;
    37             if (p[i].y < 0)  flag2 = 1;
    38             if (p[i].y < 0)  p[i].y = -p[i].y;
    39         }
    40         if (flag1 && flag2)
    41         {
    42             printf("-1
    ");
    43             continue;
    44         }
    45     
    46         double l = 0, r = 1e15, mid;        //直接枚举圆的半径,范围大约是1e7的平方
    47         int cnt = 100;                //二分100次精度足够了
    48         while (cnt--)                //这里写成(r - l) < esp陷入了死循环。。。
    49         {
    50              mid = (r + l) / 2.0;
    51             if (judge(mid)) r = mid;
    52             else  l = mid;
    53         }
    54         printf("%.10lf
    ", r);
    55     }
    56     return 0;
    57 }

     方法二

    分析:设圆心的横坐标为x,由勾股定理有(x-x0)2 + (r-y)2 = r2,得r = (x-x0)2/2y + y/2,所以R = max(r1,r2,,,rn),也就是说x确定时,R也随之确定。

    我们又发现,对于答案所在得X,在它左右走R都会单调递增,形成像山谷那样得形状,那么直接三分X直接找到谷底即可。

    具体的三分做法如下:

    设答案所在区间为(l,r),dx = (r-l)/3,则mr = r+dx,ml = l-dx。设cal(x)是计算圆心在x时r的值,若cal(ml) < cal(mr),有两种情况,异侧如①,同侧如③,所以将r更新为mr,而不是更新为ml,同理,若cal(ml) > cal(mr),则将l更新为ml。

    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 const int maxn = 100000 + 10;
     7 const double esp = 1e-6;
     8 struct Piont
     9 {
    10     double x, y;
    11 }p[maxn];
    12 int n;
    13 
    14 double cal(double x)
    15 {
    16     double r = 0;
    17     for (int i = 0; i < n; i++)
    18         r = max(r, p[i].y / 2.0 + (x - p[i].x) * (x - p[i].x) / p[i].y / 2.0);
    19     return r;
    20 }
    21 
    22 int main()
    23 {
    24     while (scanf("%d",&n) == 1)
    25     {
    26         int flag1 = 0, flag2 = 0;
    27         for (int i = 0; i < n; i++)
    28         {
    29             scanf("%lf%lf", &p[i].x, &p[i].y);
    30             if (p[i].y > 0)  flag1 = 1;
    31             if (p[i].y < 0)  flag2 = 1;
    32             if (p[i].y < 0)  p[i].y = -p[i].y;
    33         }
    34         if (flag1 && flag2)
    35         {
    36             printf("-1
    ");
    37             continue;
    38         }
    39         //R=y1/2 + (x-x1)^2/2y,x是圆心坐标,R关于x先减后增
    40         double l = -1e7, r = 1e7,dx;        //枚举圆的半径,也就是枚举圆心横坐标
    41         while (r - l > esp)                    //也可改成cnt<100
    42         {
    43             dx = (r - l) / 3.0;
    44             double lx = l + dx, rx = r - dx;
    45             if (cal(lx) - cal(rx) < 0)  r = rx;
    46             else  l = lx;
    47         }
    48         int tmp = cal(r);
    49         printf("%.6lf
    ", cal(r));
    50     }
    51     return 0;
    52 }

    参考链接:

    https://blog.csdn.net/lzc504603913/article/details/82949923

    https://blog.csdn.net/qq_37555704/article/details/82949337

    http://www.cnblogs.com/sdfzhsz/p/9748360.html

    https://blog.csdn.net/winter2121/article/details/82949159?tdsourcetag=s_pctim_aiomsg

  • 相关阅读:
    Android系统根文件系统目录结构
    4面 晶晨半导体 问题总结
    linux 工作队列
    Linux tasklet 的测试
    ArbotiX-M引脚说明
    locobot
    视频地址
    S1雷达ROS包更新指南
    rospy
    mx-28在 labview环境下的开发
  • 原文地址:https://www.cnblogs.com/lfri/p/9944289.html
Copyright © 2011-2022 走看看