zoukankan      html  css  js  c++  java
  • 【计算几何】奇特的门

    题目描述

    大厨非常擅长烹饪,他做的菜是城镇最好的,因此他打算装饰一下他的餐厅。顾客到店第一眼看到的是餐厅的门,所以大厨想从装饰门开始。他昨晚已经想出了一个新的设计,从门上挖去一些圆形,再在这些位置装上玻璃,让玻璃形成奇特的形状。

    形式上,我们可以将大厨的一系列过程抽象为以下过程。令门为一个坐标平面上以 (0,0),(W,0),(0,H),(W,H) 为四角的矩形。一开始门是白色的,而坐标平面其他部分是黑色的。每一步大厨会将一个圆的内部涂黑。在他涂完所有圆之后,他将门内的黑色部分(在代表门的矩形内的黑色部分)挖掉,并装上玻璃。

    门的奇特程度可以用窗户在门内的边界的周长表示(请参考样例中第二组数据理解)。大厨在涂色之后已经很疲惫了,他请你算出这个数。

    输入格式

    第一行一个整数 T,表示数据组数。下面是 T 组测试数据。

    每组数据第一行有三个整数 W,H,N,代表门的尺寸和圆的数量。

    下面 N 行描述 N 个圆,第 i 行有三个实数 X,Y,R,每个数恰好保留了两位小数,表示大厨第 i 步挖掉的圆的圆心坐标和半径。

    输出格式

    对于每组测试数据,输出一行表示问题描述中所指的窗户周长之和。(四舍五入保留 5 位小数)

    样例

    input

    2
    8 10 8
    2.00 2.00 1.00
    4.00 2.00 0.50
    6.00 2.00 1.00
    4.00 5.00 1.50
    3.00 6.00 0.50
    3.00 7.00 0.75
    5.00 7.00 1.00
    4.00 8.00 1.00
    7 7 3
    1.00 1.00 2.00
    3.00 3.00 1.50
    6.00 5.00 1.50
    
    

    output

    33.64043
    17.20584
    
    

    explanation

    第一组数据:答案是下图中粗线的长度总和

    img

    第二组数据:答案是下图中粗线的长度总和

    img

    限制与约定

    对于 10% 的数据,N1

    对于 30% 的数据,N2

    对于另外 50% 数据,所有圆不与矩形相交。

    对于 60% 的数据,N100

    对于 100% 的数据,1N,T,W,H10000<R10000X,Y1000

    在输入中 N 的和不超过 5000

    X,Y,R 均恰好保留两位小数。

    所有圆都是不同的,任意两个圆要么圆心不同,要么半径不同。

    时间限制:1s

    空间限制:256MB

     

    ========================================华丽丽的分割线======================================

    这是一个集训的题目,基础计算几何吧。

    由于n只有5000,考虑每个圆对答案的贡献度。

    对于每一个圆,枚举和它相交的圆,于是我们可以得到很多pair,每个pair记录被遮住的部分。

    然后每个圆,和四条直线分别判断一下。

    让我WA哭的细节在于,一个pair本质意义是所有部分全部遮住,但是会被判断成只遮住了一个点,所以这个情况需要特判。

    然后对于每一个圆,把所有的pair排序一下扫一遍就可以统计答案了。

    震惊!这题std没有eps!

    时间复杂度O(n^2logn),代码如下:

      1 #include <bits/stdc++.h>
      2 #define Maxn 6007
      3 #define double long double
      4 #define abs fabsl
      5 using namespace std;
      6 int read()
      7 {
      8     int x=0,f=1;char ch=getchar();
      9     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     10     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     11     return x*f;
     12 }
     13 int T,n;
     14 double H,W;
     15 double x[Maxn],y[Maxn],r[Maxn];
     16 pair<double,double> s[Maxn*2];
     17 double alpha1,alpha2,alpha,p,q;
     18 double a,b,c;
     19 double ans;
     20 double arccos(double x)
     21 {
     22     if (x<-1.0) x=-1.0;
     23     if (x>1.0) x=1.0;
     24     return (double)acosl(x);
     25 }
     26 int main()
     27 {
     28     T=read();
     29     while (T--)
     30     {
     31         W=1.0*read(),H=1.0*read(),n=read();
     32         for (int i=1;i<=n;i++)
     33             scanf("%Lf%Lf%Lf",&x[i],&y[i],&r[i]);
     34         ans=0.0;
     35         for (int i=1;i<=n;i++)
     36         {
     37             int cnt=0;
     38             memset(s,0,sizeof(s));
     39             for (int j=1;j<=n;j++)
     40                 if (j!=i)
     41                 {
     42                     alpha1=atan2l(1.0*(y[j]-y[i]),1.0*(x[j]-x[i]));
     43                     a=(double)sqrtl(1.0*(y[j]-y[i])*(y[j]-y[i])+1.0*(x[j]-x[i])*(x[j]-x[i]));
     44                     b=1.0*r[i],c=1.0*r[j];
     45                     if (a>=b+c) continue;
     46                     alpha2=arccos((double)((1.0*a*a+1.0*b*b-1.0*c*c))/(2.0*a*b));
     47                     p=alpha1-alpha2,q=alpha1+alpha2;
     48                     if (abs(b-c)>a&&r[i]<r[j]) p=0.0,q=2*M_PI;
     49                     if (p<0) p+=2*M_PI;
     50                     if (q<0) q+=2*M_PI;
     51                     if (p>=2*M_PI) p-=2*M_PI;
     52                     if (q>=2*M_PI) q-=2*M_PI;
     53                     if (alpha2>=M_PI) p=0.0,q=2*M_PI;
     54                     if (p<=q) s[++cnt]=make_pair(p,q);
     55                     else
     56                     {
     57                         s[++cnt]=make_pair(p,2*M_PI);
     58                         s[++cnt]=make_pair(0.0,q);
     59                     }
     60                 }
     61             if (y[i]-r[i]<0)
     62             {
     63                 alpha=arccos((double)(y[i])/(r[i]));
     64                 p=1.5*M_PI-alpha,q=1.5*M_PI+alpha;
     65                 if (p<0) p+=2*M_PI;
     66                 if (q<0) q+=2*M_PI;
     67                 if (p>=2*M_PI) p-=2*M_PI;
     68                 if (q>=2*M_PI) q-=2*M_PI;
     69                 if (alpha>=M_PI) p=0.0,q=2*M_PI;
     70                 if (p<=q) s[++cnt]=make_pair(p,q);
     71                 else
     72                 {
     73                     s[++cnt]=make_pair(p,2*M_PI);
     74                     s[++cnt]=make_pair(0.0,q);
     75                 }
     76             }
     77             if (y[i]+r[i]>H)
     78             {
     79                 alpha=arccos((double)((H-y[i])/(r[i])));
     80                 p=0.5*M_PI-alpha,q=0.5*M_PI+alpha;
     81                 if (p<0) p+=2*M_PI;
     82                 if (q<0) q+=2*M_PI;
     83                 if (p>=2*M_PI) p-=2*M_PI;
     84                 if (q>=2*M_PI) q-=2*M_PI;
     85                 if (alpha>=M_PI) p=0.0,q=2*M_PI;
     86                 if (p<=q) s[++cnt]=make_pair(p,q);
     87                 else
     88                 {
     89                     s[++cnt]=make_pair(p,2*M_PI);
     90                     s[++cnt]=make_pair(0.0,q);
     91                 }
     92             }
     93             if (x[i]-r[i]<0)
     94             {
     95                 alpha=arccos((double)(x[i])/(r[i]));
     96                 p=M_PI-alpha,q=M_PI+alpha;
     97                 if (p<0) p+=2*M_PI;
     98                 if (q<0) q+=2*M_PI;
     99                 if (p>=2*M_PI) p-=2*M_PI;
    100                 if (q>=2*M_PI) q-=2*M_PI;
    101                 if (alpha>=M_PI) p=0.0,q=2*M_PI;
    102                 if (p<=q) s[++cnt]=make_pair(p,q);
    103                 else
    104                 {
    105                     s[++cnt]=make_pair(p,2*M_PI);
    106                     s[++cnt]=make_pair(0.0,q);
    107                 }
    108             }
    109             if (x[i]+r[i]>W)
    110             {
    111                 alpha=arccos((double)((W-x[i]))/(r[i]));
    112                 p=2*M_PI-alpha,q=alpha;
    113                 if (p<0) p+=2*M_PI;
    114                 if (q<0) q+=2*M_PI;
    115                 if (p>=2*M_PI) p-=2*M_PI;
    116                 if (q>=2*M_PI) q-=2*M_PI;
    117                 if (alpha>=M_PI) p=0.0,q=2*M_PI;
    118                 if (p<=q) s[++cnt]=make_pair(p,q);
    119                 else
    120                 {
    121                     s[++cnt]=make_pair(p,2*M_PI);
    122                     s[++cnt]=make_pair(0.0,q);
    123                 }
    124             }
    125             sort(s+1,s+cnt+1);
    126             double del=0.0,rmax=0.0;
    127             del+=s[1].first;
    128             rmax=s[1].second;
    129             for (int j=2;j<=cnt;j++)
    130             {
    131                 if (s[j].first>rmax) del+=(s[j].first-rmax);
    132                 rmax=max(rmax,s[j].second);
    133             }
    134             if (2*M_PI>rmax) del+=(2*M_PI-rmax);
    135             ans+=r[i]*del;
    136         }
    137         printf("%.5Lf
    ",ans);
    138     }
    139     return 0;
    140 }
  • 相关阅读:
    QQ邮箱开启SMTP服务的步骤
    delete
    (三)----使用HttpClient发送HTTP请求(分别通过GET和POST方法发送数据)
    (四)SAX方式解析XML数据
    If-Modified-Since页面是否更新
    基于分块统计和机器学习的主题类网页内容识别算法实现和应用范例
    文本去重第一步:基于内容的文本相似性计算
    java中int,float,long,double取值范围,内存泄露
    Linux多线程服务端编程:使用muduo C++网络库
    HttpClient使用详解
  • 原文地址:https://www.cnblogs.com/Tommyr7/p/6993806.html
Copyright © 2011-2022 走看看