Harry Potter and J.K.Rowling HDU

Harry Potter and J.K.Rowling

HDU - 3982

题意:半平面交 + 圆与多边形的面积并.

转换成圆与三角形的面积并,分四种情况讨论一下.

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 const double pi = acos(-1.0);
  4 const int maxn = 2010;
  5 const int inf = 0x3f3f3f3f;
  6 const double eps = 1e-8;
  7 struct Point {
  8     double x,y;
  9     Point (double x = 0, double y = 0) : x(x), y(y) {}
 10 };
 11 typedef Point Vector;
 12 struct Circle{
 13     Point o;
 14     double r;
 15     Circle(){}
 16     Circle(Point o, double r) : o(o), r(r){}
 17     //Point point(double a){
 18     //    return Point(o.x + cos(a)*r, o.y + sin(a)*r);
 19     //}
 20 };
 21 Vector operator + (Vector a, Vector b) {
 22     return Vector (a.x + b.x, a.y + b.y);
 23 }
 24 Vector operator * (Vector a, double s) {
 25     return Vector (a.x * s, a.y * s);
 26 }
 27 Vector operator / (Vector a, double p) {
 28     return Vector (a.x / p, a.y / p);
 29 }
 30 Vector operator - (Point a, Point b) {
 31     return Vector (a.x - b.x, a.y - b.y);
 32 }
 33 bool operator < (Point a, Point b) {
 34     return a.x < b.x || (a.x == b.x && a.y < b.y);
 35 }
 36 int dcmp (double x) {
 37     if(fabs(x) < eps) return 0;
 38     return x < 0 ? -1 : 1;
 39 }
 40 bool operator == (const Point &a, const Point &b) {
 41     return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
 42 }
 43 double Dot(Vector a, Vector b) {
 44     return a.x * b.x + a.y * b.y;
 45 }
 46 double Angle(Vector a){
 47     return atan2(a.y, a.x);
 48 }
 49 double Length(Vector a) {
 50     return sqrt(Dot(a, a));
 51 }
 52 double Cross (Vector a, Vector b) {
 53     return a.x * b.y - a.y * b.x;
 54 }
 55 //半平面交
 56 struct Line {
 57     Point p;
 58     Vector v;
 59     double rad;
 60     Line () {}
 61     Line (Point p, Vector v) : p(p), v(v) {
 62         rad = atan2(v.y,v.x);
 63     }
 64     bool operator < (const Line &L) const {
 65         return rad < L.rad;
 66     }
 67 };
 68 bool OnLeft(Line L, Point p) {
 69     return Cross(L.v, p - L.p) > 0;
 70 }
 71 Point GetLineIntersection (Line a, Line b) {
 72     Vector u = a.p - b.p;
 73     double t = Cross(b.v, u) / Cross(a.v, b.v);
 74     return a.p + a.v*t;
 75 }
 76 
 77 int HalfplaneIntersection(Line *L, int n,Point *poly) {
 78     sort(L, L+n);
 79     int first,last;
 80     Point *p = new Point[n];
 81     Line *q = new Line[n];  //双端队列
 82     q[first = last = 0] = L[0];
 83     for(int i = 1; i < n; i++) {
 84         while(first < last && !OnLeft(L[i], p[last-1])) last--;   //去尾
 85         while(first < last && !OnLeft(L[i], p[first])) first++; 
 86         q[++last] = L[i];
 87         if(dcmp(Cross(q[last].v, q[last-1].v)) == 0) {
 88             last--;
 89             if(OnLeft(q[last], L[i].p)) q[last] = L[i];
 90         }
 91         if(first < last) p[last-1] = GetLineIntersection (q[last-1],q[last]);
 92     }
 93     while(first < last && !OnLeft(q[first], p[last-1])) last--;  //删除无用平面
 94     if(last - first <= 1) {
 95         delete []p;
 96         delete []q;
 97        return 0;  //空集    
 98     }
 99     p[last] = GetLineIntersection (q[last], q[first]);
100     int m = 0;
101     for(int i = first; i <= last; i++) poly[m++] = p[i];
102     delete []p;
103     delete []q;
104     return m;
105 }
106 Point p[maxn][2], poly[maxn];
107 Line line[maxn];
108 Circle cr;
109 Point goal;
110 //线段AB与圆的交点
111 void LineIntersectionCircle(Point A, Point B, Circle cr, Point *p, int &num){
112     double x0 = cr.o.x, y0 = cr.o.y;
113     double x1 = A.x, y1 = A.y, x2 = B.x, y2 = B.y;
114     double dx = x2 - x1, dy = y2 - y1;
115     double a = dx * dx + dy * dy;
116     double b = 2 * dx *(x1 - x0) + 2 * dy * (y1 -y0);
117     double c = (x1 - x0) * (x1 - x0) + (y1 - y0) * (y1 - y0) - cr.r *cr.r;
118     double delta = b*b - 4*a*c;
119     num = 0;
120     if(dcmp(delta) >= 0){
121         double t1 = (-b - sqrt(delta)) / (2*a);
122         double t2 = (-b + sqrt(delta)) / (2*a);
123         if(dcmp(t1-1) <= 0 && dcmp(t1) >= 0) {
124             p[num++] = Point(x1 + t1*dx, y1 + t1*dy);
125         }
126         if(dcmp(t2-1) <= 0 && dcmp(t2) >= 0) {
127             p[num++] = Point(x1 + t2*dx, y1 + t2*dy);
128         }
129     }
130 }
131 //扇形面积
132 double SectorArea(Point a, Point b, Circle cr){
133     double theta = Angle(a - cr.o) - Angle(b - cr.o);
134     while(theta <= 0) theta += 2*pi;
135     while(theta > 2*pi) theta -= 2*pi;
136     theta = min(theta, 2*pi - theta);
137     return cr.r * cr.r * theta / 2;
138 }
139 
140 double cal(Point a, Point b, Circle cr){
141     Point tp[3];
142     int num = 0;
143     Vector ta = a - cr.o;
144     Vector tb = b - cr.o;
145     bool ina = (Length(ta) - cr.r) < 0;
146     bool inb = (Length(tb) - cr.r) < 0;
147     if(ina){
148         if(inb){
149             return fabs(Cross(ta, tb))/2;
150         } else{
151             LineIntersectionCircle(a, b, cr, tp, num); 
152             return SectorArea(b, tp[0], cr) + fabs(Cross(ta, tp[0] - cr.o))/2;
153         }
154     } else{
155         if(inb){
156             LineIntersectionCircle(a, b, cr, tp, num); 
157             return SectorArea(a, tp[0], cr) + fabs(Cross(tb, tp[0] - cr.o))/2;
158         } else {
159             LineIntersectionCircle(a, b, cr, tp, num); 
160             if(num == 2) {
161                 return SectorArea(a, tp[0], cr) + SectorArea(b, tp[1], cr) + fabs(Cross(tp[0]-cr.o, tp[1]-cr.o))/2;
162             } else {
163                 return SectorArea(a, b, cr);
164             }
165         }
166     }
167 }
168 //圆与多边形的面积并
169 double CirclePolyArea(Point *p, int n, Circle cr){
170    double res = 0;
171    p[n] = p[0];
172    for(int i = 0; i < n; i++){
173        int sgn = dcmp(Cross(p[i] - cr.o, p[i+1] - cr.o));
174        if(sgn){
175            res += sgn * cal(p[i], p[i+1], cr);
176        }
177    }
178    return res;
179 }
180 
181 
182 int main(){
183     //freopen("in.txt", "r", stdin);
184     int t, kase = 0;
185     scanf("%d", &t);
186     while(t--){
187         int n;
188         double r;
189         scanf("%lf %d", &r, &n);
190         cr.r = r;
191         cr.o = Point(0, 0);
192         for(int i = 0; i < n; i++){
193             for(int j = 0; j < 2; j++){
194                 scanf("%lf %lf", &p[i][j].x, &p[i][j].y);
195             }
196         }
197         scanf("%lf %lf", &goal.x, &goal.y);
198         for(int i = 0; i < n; i++){
199             Line lp = Line(p[i][0], p[i][0] - p[i][1]);
200             if(OnLeft(lp, goal)){
201                 line[i] = lp;
202             }else {
203                 line[i] = Line(p[i][0], p[i][1] - p[i][0]);
204             }
205         }
206         Point p1 = Point(-11111, -11111), p2 = Point(-11111, 11111);
207         Point p3 = Point(11111, 11111), p4 = Point(11111, -11111);
208         line[n] = Line(p1, p1-p2);
209         line[n+1] = Line(p2, p2-p3);
210         line[n+2] = Line(p3, p3-p4);
211         line[n+3] = Line(p4, p4-p1);
212         int sz = HalfplaneIntersection(line, n+4, poly);
213         double area = CirclePolyArea(poly, sz, cr);
214         printf("Case %d: %.5lf", ++kase, area/pi/r/r*100);
215         puts("%");
216     }
217     return 0;
218 }
View Code
原文地址:https://www.cnblogs.com/yijiull/p/7688290.html