zoukankan      html  css  js  c++  java
  • CF613A:Peter and Snow Blower

    用一个圆心在(x,y)的圆环覆盖一个n边形,顺或逆时针给出n边形所有顶点,求圆环最小面积。

    卡了好久,各种傻逼错误。。

    题目就是让我们固定一大一小两个边界圆,我们来看看这两个圆满足什么条件。

    首先外面的那个圆肯定是经过n边形的某个顶点,所以外圆半径就是最大的点距。

    其次内圆呢,可能经过一个点,也可能与某条边相切,但注意,这里的线是线段不是直线!

    所以可能会出现最后的内圆和某条“直线”相交而与其对应的线段没有交点。例如:

    上图中内圆与四条“直线”都相交,但与“线段”只有一个交点。

    为了判断内圆,我用了最粗暴的方法--二分,计算与当前半径的圆相交的“直线“的两个交点是否在“线段”上,用横坐标或纵坐标判断。

    Trick:

    如果是用y=kx+b就会wa,因为平面上不是所有的直线都能这么表示,要用一般式Ax+By+C=0。

    计算圆与直线相交情况时记得分B是否为0的情况。所有计算过程中记得判断除0情况。

    精度。二分时在精度那里要注意R-eps或者L+eps,不然可能tle。

      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<algorithm>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 //#include<iostream>
      8 using namespace std;
      9 
     10 int n;
     11 #define maxn 100011
     12 struct Point
     13 {
     14     double x,y;
     15 }a[maxn],P;
     16 struct Line
     17 {
     18     double a,b,c,dis;
     19 }l[maxn];
     20 const double eps=1e-10,pi=3.1415926535897932384626434;
     21 void do_line(int id,double x1,double y1,double x2,double y2)
     22 {
     23     if (x1==x2)
     24     {
     25         l[id].a=1;
     26         l[id].b=0;
     27         l[id].c=-x1;
     28     }
     29     else if (y1==y2)
     30     {
     31         l[id].a=0;
     32         l[id].b=1;
     33         l[id].c=-y1;
     34     }
     35     else if (x2*y1==x1*y2)
     36     {
     37         l[id].c=0;
     38         l[id].a=233333;
     39         if (y1) l[id].b=-x1/y1*l[id].a;
     40         else l[id].b=-x2/y2*l[id].a;
     41     }
     42     else
     43     {
     44         l[id].c=100000;
     45         l[id].a=l[id].c*(y2-y1)/(x2*y1-x1*y2);
     46         l[id].b=l[id].c*(x2-x1)/(y2*x1-y1*x2);
     47     }
     48     l[id].dis=abs(l[id].a*P.x+l[id].b*P.y+l[id].c)/sqrt(l[id].a*l[id].a+l[id].b*l[id].b);
     49 }
     50 double ppdissqr(double x1,double y1,double x2,double y2)
     51 {
     52     return (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);
     53 }
     54 bool judge(double x)
     55 {
     56     for (int i=1;i<=n;i++)
     57         if (l[i].dis-x<=-eps)
     58         {
     59             double A=l[i].a,B=l[i].b,C=l[i].c;
     60             if (B)
     61             {
     62                 double delta=((A/B)*(A/B)+1)*x*x-((A*P.x+C)/B+P.y)*((A*P.x+C)/B+P.y),
     63                 x1=(-2*(A/B*(C/B+P.y)-P.x)+sqrt(delta))/(2*(1+(A/B)*(A/B))),
     64                 x2=(-2*(A/B*(C/B+P.y)-P.x)-sqrt(delta))/(2*(1+(A/B)*(A/B)));
     65                 double p=a[i].x,q=a[i+1].x;
     66                 if (i==n) q=a[1].x;
     67                 if (p>q) swap(p,q);
     68                 if ((x1>=p && x1<=q)
     69                 || (x2>=p && x2<=q))
     70                 return 0;
     71             }
     72             else
     73             {
     74                 double y1=P.y+sqrt(x*x-(-C/A-P.x)*(-C/A-P.x)),
     75                        y2=P.y-sqrt(x*x-(-C/A-P.x)*(-C/A-P.x));
     76                 double p=a[i].y,q=a[i+1].y;
     77                 if (i==n) q=a[1].y;
     78                 if (p>q) swap(p,q);
     79                 if ((y1>=p && y1<=q)
     80                 || (y2>=p && y2<=q))
     81                 return 0;
     82             }
     83         }
     84     return 1;
     85 }
     86 int main()
     87 {
     88     scanf("%d%lf%lf",&n,&P.x,&P.y);
     89     for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].x,&a[i].y);
     90     for (int i=1;i<n;i++)
     91         do_line(i,a[i].x,a[i].y,a[i+1].x,a[i+1].y);
     92     do_line(n,a[n].x,a[n].y,a[1].x,a[1].y);
     93     double f1=0.0,r2,L=0.0,R;
     94     for (int i=1;i<=n;i++)
     95         f1=max(f1,ppdissqr(a[i].x,a[i].y,P.x,P.y));
     96     R=sqrt(f1);
     97     for (int i=1;i<=n;i++)
     98         R=min(R,sqrt(ppdissqr(a[i].x,a[i].y,P.x,P.y)));
     99     while (R-L>eps)
    100     {
    101         double mid=(L+R+eps)/2;
    102         if (judge(mid)) L=mid;
    103         else R=mid-eps;
    104     }
    105     r2=(L+R)/2;
    106     printf("%.10lf
    ",pi*(f1-r2*r2));
    107     return 0;
    108 }
    View Code
  • 相关阅读:
    Time Zone 【模拟时区转换】(HDU暑假2018多校第一场)
    HDU 1281 棋盘游戏 【二分图最大匹配】
    Codeforces Round #527 (Div. 3) F. Tree with Maximum Cost 【DFS换根 || 树形dp】
    Codeforces Round #527 (Div. 3) D2. Great Vova Wall (Version 2) 【思维】
    Codeforces Round #527 (Div. 3) D1. Great Vova Wall (Version 1) 【思维】
    Codeforces Round #528 (Div. 2, based on Technocup 2019 Elimination Round 4) C. Connect Three 【模拟】
    Avito Cool Challenge 2018 E. Missing Numbers 【枚举】
    Avito Cool Challenge 2018 C. Colorful Bricks 【排列组合】
    005 如何分析问题框架
    004 如何定义和澄清问题
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7193262.html
Copyright © 2011-2022 走看看