【计算几何】奇特的门

题目描述

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

形式上,我们可以将大厨的一系列过程抽象为以下过程。令门为一个坐标平面上以 (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 }
原文地址:https://www.cnblogs.com/Tommyr7/p/6993806.html