BZOJ 1043 圆弧覆盖

为按照极角,转化为线段覆盖问题。

这题有个特别混蛋的trick,就是后掉落的把先掉落的完全覆盖了,我就没考虑这个,无限wa啊!!

View Code
  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <algorithm>
  5 #include <cstdlib>
  6 #include <cmath>
  7 #include <vector>
  8 
  9 #define N 1111
 10 #define PI 3.14159265358979323846
 11 #define EPS 1e-7
 12 
 13 using namespace std;
 14 
 15 struct PO
 16 {
 17     double x,y,r;
 18     void prt() {printf("%lf     %lf\n",x,y);}
 19 }p[N];
 20 
 21 struct V
 22 {
 23     int fg; double f;
 24 };
 25 vector<V> v[N];
 26 
 27 int n;
 28 double sum,ans;
 29 bool vis[N];
 30 
 31 inline int dc(double x)
 32 {
 33     if(x>EPS) return 1;
 34     else if(x<-EPS) return -1;
 35     return 0;
 36 }
 37 
 38 inline bool cmp(const V &a,const V &b)
 39 {
 40     if(a.f==b.f) return a.fg>b.fg;
 41     return a.f<b.f;
 42 }
 43 
 44 inline PO operator -(PO a,PO b)
 45 {
 46     a.x-=b.x; a.y-=b.y;
 47     return a;
 48 }
 49 
 50 inline PO operator +(PO a,PO b)
 51 {
 52     a.x+=b.x; a.y+=b.y;
 53     return a;
 54 }
 55 
 56 inline PO operator *(PO a,double k)
 57 {
 58     a.x*=k; a.y*=k;
 59     return a;
 60 }
 61 
 62 inline PO operator /(PO a,double k)
 63 {
 64     a.x/=k; a.y/=k;
 65     return a;
 66 }
 67 
 68 inline double getlen(const PO &a)
 69 {
 70     return sqrt(a.x*a.x+a.y*a.y);
 71 }
 72 
 73 inline double getdis(const PO &a,const PO &b)
 74 {
 75     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
 76 }
 77 
 78 inline PO rotate(const PO &a,double sss,double ccc)
 79 {
 80     PO rt;
 81     rt.x=a.x*ccc-a.y*sss;
 82     rt.y=a.x*sss+a.y*ccc;
 83     return rt;
 84 }
 85 
 86 inline void read()
 87 {
 88     scanf("%d",&n);
 89     for(int i=1;i<=n;i++)
 90         scanf("%lf%lf%lf",&p[i].r,&p[i].x,&p[i].y);
 91 }
 92 
 93 inline void getcpoint(const PO &a,const PO &b,PO &s,PO &t)//求圆的交点,a的逆时针方向的弧上的点 
 94 {
 95     PO ab=b-a;
 96     double d=getlen(ab);
 97     double ccc=(b.r*b.r-d*d-a.r*a.r)/(-2.0*a.r*d);
 98     double sss=sqrt(1.0-ccc*ccc);
 99     ab=ab/d*a.r;
100     s=a+rotate(ab,-sss,ccc);
101     t=a+rotate(ab,sss,ccc);
102 }
103 
104 inline void go()
105 {
106     PO a,b; V c;
107     double f1,f2;
108     for(int i=1;i<=n;i++)
109         for(int j=i+1;j<=n;j++)
110         {
111             double dis=getdis(p[i],p[j]);
112             if(dis+1e-10>p[i].r+p[j].r || p[j].r+1e-10<p[i].r&&dis-1e-10<p[i].r-p[j].r) continue;
113             if(p[i].r<p[j].r+1e-10&&dis-1e-10<p[j].r-p[i].r) {vis[i]=true; break;}
114             getcpoint(p[i],p[j],a,b);
115             f1=atan2(a.y-p[i].y,a.x-p[i].x);
116             f2=atan2(b.y-p[i].y,b.x-p[i].x);
117             if(f1>f2)
118             {
119                 c.f=f1; c.fg=1; v[i].push_back(c);
120                 c.f=PI; c.fg=-1; v[i].push_back(c);
121                 c.f=-PI; c.fg=1; v[i].push_back(c);
122                 c.f=f2; c.fg=-1; v[i].push_back(c);
123             }
124             else
125             {
126                 c.f=f1; c.fg=1; v[i].push_back(c);
127                 c.f=f2; c.fg=-1; v[i].push_back(c);
128             }
129         }
130     for(int i=1;i<=n;i++)
131     {
132         if(vis[i]) continue;
133         sum+=2*PI*p[i].r;
134         sort(v[i].begin(),v[i].end(),cmp);
135         int tmp=0; double last;
136         for(int j=0;j<v[i].size();j++)
137         {
138             tmp+=v[i][j].fg;
139             if(tmp==1&&v[i][j].fg==1) last=v[i][j].f;
140             else if(tmp==0&&v[i][j].fg==-1) ans+=(v[i][j].f-last)*p[i].r;
141         }
142     }
143     printf("%.3lf\n",sum-ans);
144 }
145 
146 int main()
147 {
148     read(),go();
149     return 0;
150 }
没有人能阻止我前进的步伐,除了我自己!
原文地址:https://www.cnblogs.com/proverbs/p/2956762.html