uva 12296 Pieces and Discs

题意:

有个矩形,左下角(0,0),左上角(L,W).

思路:

除了圆盘之外,本题的输入也是个PSLG,因此可以按照前面叙述的算法求出各个区域:只需把线段视为直线,用切割凸多边形的方法 :每次读入线段,切割所有块,最终得到若干凸多边形

如何判断多边形是否与圆盘相交:如果多边形的边和圆周规范相交,圆盘和多边形一定相交,

 1:即使完全没有公共点,也可以相交,互相内含 需要判断多边形是否有顶点在园内,还需要判断圆心是否在多边形内;

2.如果不规范:  a:带判断的线段在园外;

b:带判断的线段在园内即两个端点在圆上,只需要判断中点是否在园内;

  1 #include<cstdio>
  2 #include<cmath>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<iostream>
  6 #include<memory.h>
  7 #include<cstdlib>
  8 #include<vector>
  9 #define clc(a,b) memset(a,b,sizeof(a))
 10 #define LL long long int
 11 #define up(i,x,y) for(i=x;i<=y;i++)
 12 #define w(a) while(a)
 13 const double inf=0x3f3f3f3f;
 14 const double eps = 1e-8;
 15 const double PI = acos(-1.0);
 16 using namespace std;
 17 
 18 double dcmp(double x)
 19 {
 20     if(fabs(x) < eps) return 0;
 21     else return x < 0 ? -1 : 1;
 22 }
 23 
 24 struct Point
 25 {
 26     double x, y;
 27     Point(double x=0, double y=0):x(x),y(y) { }
 28 };
 29 
 30 typedef Point Vector;
 31 
 32 typedef vector<Point> Polygon;
 33 
 34 Vector operator + (Vector A, Vector B)
 35 {
 36     return Vector(A.x+B.x, A.y+B.y);
 37 }
 38 
 39 Vector operator - (Point A, Point B)
 40 {
 41     return Vector(A.x-B.x, A.y-B.y);
 42 }
 43 
 44 Vector operator * (Vector A, double p)
 45 {
 46     return Vector(A.x*p, A.y*p);
 47 }
 48 
 49 double Dot(Vector A, Vector B)
 50 {
 51     return A.x*B.x + A.y*B.y;
 52 }
 53 double Cross(Vector A, Vector B)
 54 {
 55     return A.x*B.y - A.y*B.x;
 56 }
 57 double Length2(Vector A)
 58 {
 59     return Dot(A, A);
 60 }
 61 
 62 Point GetLineIntersection(Point P, Vector v, Point Q, Vector w)
 63 {
 64     Vector u = P-Q;
 65     double t = Cross(w, u) / Cross(v, w);
 66     return P+v*t;
 67 }
 68 
 69 bool OnSegment(Point p, Point a1, Point a2)
 70 {
 71     return dcmp(Cross(a1-p, a2-p)) == 0 && dcmp(Dot(a1-p, a2-p)) < 0;
 72 }
 73 
 74 // 多边形的有向面积
 75 double PolygonArea(Polygon poly)
 76 {
 77     double area = 0;
 78     int n = poly.size();
 79     for(int i = 1; i < n-1; i++)
 80         area += Cross(poly[i]-poly[0], poly[(i+1)%n]-poly[0]);
 81     return area/2;
 82 }
 83 
 84 // cut with directed line A->B, return the left part
 85 // may return a single point or a line segment
 86 Polygon CutPolygon(Polygon poly, Point A, Point B)
 87 {
 88     Polygon newpoly;
 89     int n = poly.size();
 90     for(int i = 0; i < n; i++)
 91     {
 92         Point C = poly[i];
 93         Point D = poly[(i+1)%n];
 94         if(dcmp(Cross(B-A, C-A)) >= 0) newpoly.push_back(C);
 95         if(dcmp(Cross(B-A, C-D)) != 0)
 96         {
 97             Point ip = GetLineIntersection(A, B-A, C, D-C);
 98             if(OnSegment(ip, C, D)) newpoly.push_back(ip);
 99         }
100     }
101     return newpoly;
102 }
103 
104 int isPointInPolygon(Point p, Polygon v)
105 {
106     int wn = 0;
107     int n = v.size();
108     for(int i = 0; i < n; i++)
109     {
110         if(OnSegment(p, v[i], v[(i+1)%n])) return -1; // 在边界上
111         int k = dcmp(Cross(v[(i+1)%n]-v[i], p-v[i]));
112         int d1 = dcmp(v[i].y - p.y);
113         int d2 = dcmp(v[(i+1)%n].y - p.y);
114         if(k > 0 && d1 <= 0 && d2 > 0) wn++;
115         if(k < 0 && d2 <= 0 && d1 > 0) wn--;
116     }
117     if (wn != 0) return 1; // 内部
118     return 0; // 外部
119 }
120 
121 // 点在圆心内。圆周上不算
122 bool isInCircle(Point p, Point center, double R)
123 {
124     return dcmp(Length2(p-center) - R*R) < 0;
125 }
126 
127 // 直线AB和圆心为C,半径为r的圆的交点
128 // 返回交点个数,t1, t2分别为两个交点在直线方程中的参数,p1和p2为交点本身
129 int getLineCircleIntersection(Point A, Point B, Point C, double r, double& t1, double& t2)
130 {
131     // 初始方程:(A.x + t(B.x - A.x) - C.x)^2 + (A.y + t(B.y - A.y) - C.y)^2 = r^2
132     // 整理得:(at + b)^2 + (ct + d)^2 = r^2
133     double a = B.x - A.x;
134     double b = A.x - C.x;
135     double c = B.y - A.y;
136     double d = A.y - C.y;
137     // 展开得:(a^2 + c^2)t^2 + 2(ab + cd)t + b^2 + d^2 - r^2 = 0,即et^2 + ft + g = 0
138     double e = a * a + c * c;
139     double f = 2 * (a * b + c * d);
140     double g = b * b + d * d - r * r;
141     double delta = f * f - 4 * e * g; // 判别式
142     if(dcmp(delta) < 0) return 0; // 相离
143     if(dcmp(delta) == 0)  // 相切
144     {
145         t1 = t2 = -f / (2 * e);
146         return 1;
147     }
148     t1 = (-f - sqrt(delta)) / (2 * e);
149     t2 = (-f + sqrt(delta)) / (2 * e);
150     return 2;
151 }
152 
153 // 圆和线段是否相交(相切不算)。线段不考虑端点
154 bool CircleIntersectSegment(Point A, Point B, Point p, double R)
155 {
156     double t1, t2;
157     int c = getLineCircleIntersection(A, B, p, R, t1, t2);
158     if(c <= 1) return false;
159     if(dcmp(t1) > 0 && dcmp(t1-1) < 0) return true; // 端点在圆上
160     if(dcmp(t2) > 0 && dcmp(t2-1) < 0) return true;
161     return false;
162 }
163 
164 /////////// 题目相关
165 vector<Polygon> pieces, new_pieces;
166 
167 void cut(int x1, int y1, int x2, int y2)
168 {
169     new_pieces.clear();
170     for(int i = 0; i < pieces.size(); i++)
171     {
172         Polygon left = CutPolygon(pieces[i], Point(x1, y1), Point(x2, y2));
173         Polygon right = CutPolygon(pieces[i], Point(x2, y2), Point(x1, y1));
174         if(left.size() >= 3) new_pieces.push_back(left);
175         if(right.size() >= 3) new_pieces.push_back(right);
176     }
177     pieces = new_pieces;
178 }
179 
180 bool DiscIntersectPolygon(Polygon poly, Point p, double R)
181 {
182     if(isPointInPolygon(p, poly) != 0) return true;
183     if(isInCircle(poly[0], p, R)) return true;
184     int n = poly.size();
185     for(int i = 0; i < n; i++)
186     {
187         if(CircleIntersectSegment(poly[i], poly[(i+1)%n], p, R))
188         {
189             return true; // 不考虑线段端点
190         }
191         if(isInCircle((poly[i]+poly[(i+1)%n])*0.5, p, R))
192         {
193             return true; // 两个端点都在圆上
194         }
195     }
196     return false;
197 }
198 
199 void query(Point p, int R)
200 {
201     vector<double> ans;
202     for(int i = 0; i < pieces.size(); i++)
203     {
204         if(DiscIntersectPolygon(pieces[i], p, R))
205         {
206             ans.push_back(fabs(PolygonArea(pieces[i])));
207         }
208     }
209     printf("%d", ans.size());
210     sort(ans.begin(), ans.end());
211     for(int i = 0; i < ans.size(); i++)
212         printf(" %.2lf", ans[i]);
213     printf("\n");
214 }
215 
216 int main()
217 {
218     int n, m, L, W;
219     while(scanf("%d%d%d%d", &n, &m, &L, &W) == 4 && n)
220     {
221         pieces.clear();
222 
223         Polygon bbox;
224         bbox.push_back(Point(0, 0));
225         bbox.push_back(Point(L, 0));
226         bbox.push_back(Point(L, W));
227         bbox.push_back(Point(0, W));
228         pieces.push_back(bbox);
229 
230         for(int i = 0; i < n; i++)
231         {
232             int x1, y1, x2, y2;
233             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
234             cut(x1, y1, x2, y2);
235         }
236 
237         for(int i = 0; i < m; i++)
238         {
239             int x, y, R;
240             scanf("%d%d%d", &x, &y, &R);
241             query(Point(x, y), R);
242         }
243         printf("\n");
244     }
245     return 0;
246 }
View Code

 

posted @ 2015-10-20 22:58  yyblues  阅读(222)  评论(0编辑  收藏  举报