[UVA][幾何、半平面交] 11265 - The Sultan's Problem
Problem F
The Sultan’s Problem
Input: Standard Input
Output: Standard Output
Once upon a time, there lived a greatsultan, who was very much fond of his wife. He wanted to build a Tajmahal for his wife (ya, oursultan idolized Mughal emperor Shahjahan).But alas, due to budget cuts, loans, dues and many manythings, he had no fund to build something so big. So, he decided to build abeautiful garden, inside his palace.
The garden is a rectangular pieceof land. All the palace’s water lines run through the garden, thus, dividing itinto pieces of varying shapes. He wanted to cover each piece of the land withflowers of same kind.
Figure 1
The figure above shows a sampleflower garden. All the lines are straight lines, with two end points on twodifferent edge of the rectangle. Each piece of the garden is covered with thesame kind of flowers.
The garden has a small fountain,located at position (x,y).You can assume that, it is not on any of the lines. He wants to fill that piecewith her favourite flower. So, he asks you to findthe area of that piece.
Input
Input contains around 500 testcases. Each case starts with 5 integers, N, W, H, x,y, the number of lines, width and height of the garden and the locationof the fountain. Next N lines each contain 4 integers, x1y1 x2 y2, the two end points of the line.The end points are always on the boundary of the garden. You can assume that,the fountain is not located on any line.
Output
For each test case, output thecase number, with the area of the piece covered with her favouriteflower. Print 3 digits after the decimal point.
Constraints
- 1 ≤ W, H ≤ 200,000
- 1 ≤ N ≤ 500
Sample Input | Sample Output |
3 100 100 20 30 0 0 100 100 100 0 0 100 0 40 40 100
| Case #1: 1780.000 |
Problemsetter: Manzurur Rahman Khan
Special Thanks To: Mohammad MahmudurRahman
解題思路:
一個型態 polygon,以及求一條長直線交多邊形的兩交點,
如果有交的話,將這個多邊形一分為二,同時只保留涵蓋花園的那塊
最後使用行列式算花園面積
#include <stdio.h>
#include <math.h>
struct Pt {
double x, y;
};
struct Polygon {
Pt p[505];
int n;
};
double calcArea(Polygon &p) {
static int i;
double sum = 0;
p.p[p.n] = p.p[0];
for(i = 0; i < p.n; i++)
sum += p.p[i].x*p.p[i+1].y - p.p[i].y*p.p[i+1].x;
return fabs(sum/2);
}
void print(Polygon &p) {
for(int i = 0; i < p.n; i++)
printf("%lf %lf\n", p.p[i].x, p.p[i].y);
puts("=====");
}
int main() {
int n, w, h;
int cases = 0;
int i, j, k;
double sx, sy, ex, ey, xi, yi;
while(scanf("%d %d %d", &n, &w, &h) == 3) {
scanf("%lf %lf", &xi, &yi);
Polygon A, B, C;
A.n = 4;
A.p[0].x = 0, A.p[0].y = 0;
A.p[1].x = w, A.p[1].y = 0;
A.p[2].x = w, A.p[2].y = h;
A.p[3].x = 0, A.p[3].y = h;
while(n--) {
scanf("%lf %lf %lf %lf", &sx, &sy, &ex, &ey);
// ax + by + c = 0
double a, b, c;
#define eps 1e-8
double m = (sy-ey)/(sx-ex);
if(fabs(sx-ex) < eps)
a = 1, b = 0, c = -sx;
else
a = m, b = -1, c = -(sx*a+b*sy);
//printf("%lf x + %lf y + %lf = 0\n", a, b, c);
A.p[A.n] = A.p[0];
B.n = 0, C.n = 0;
Pt intP[2];
int point = 0;
for(i = 0; i < A.n; i++) {
if(point == 1) {
if(B.n == 0 || fabs(B.p[B.n-1].x-A.p[i].x) > eps ||
fabs(B.p[B.n-1].y-A.p[i].y) > eps)
B.p[B.n++] = A.p[i];
} else {
if(C.n == 0 || fabs(C.p[C.n-1].x-A.p[i].x) > eps ||
fabs(C.p[C.n-1].y-A.p[i].y) > eps)
C.p[C.n++] = A.p[i];
}
//printf("(%lf %lf)-(%lf %lf)\n", A.p[i].x, A.p[i].y, A.p[i+1].x, A.p[i+1].y);
if((a*A.p[i].x+b*A.p[i].y+c)*(a*A.p[i+1].x+b*A.p[i+1].y+c) <= eps) {
if(point == 2) continue;
double ta, tb, tc;
double tm = (A.p[i].y-A.p[i+1].y)/(A.p[i].x-A.p[i+1].x);
if(fabs(A.p[i].x-A.p[i+1].x) < eps)
ta = 1, tb = 0, tc = -A.p[i].x;
else
ta = tm, tb = -1, tc = -(A.p[i].x*ta+A.p[i].y*tb);
// ax+by+c = 0, ta*x+tb*y+tc = 0
//printf("%lf x + %lf y + %lf = 0\n", ta, tb, tc);
double rx, ry, r;
r = a*tb-ta*b;
rx = (-c)*tb-(-tc)*b;
ry = a*(-tc)-ta*(-c);
rx = rx/r;
ry = ry/r;
if(fabs(r) < eps) continue; // no intersection
if(point == 1) {
if(fabs(rx-intP[0].x) < eps && fabs(ry-intP[0].y) < eps)
continue;
}
//printf("intersection %lf %lf\n", rx, ry);
intP[point].x = rx, intP[point].y = ry;
if(B.n == 0 || fabs(B.p[B.n-1].x-rx) > eps || fabs(B.p[B.n-1].y-ry) > eps)
B.p[B.n++] = intP[point];
if(C.n == 0 || fabs(C.p[C.n-1].x-rx) > eps || fabs(C.p[C.n-1].y-ry) > eps)
C.p[C.n++] = intP[point];
point++;
}
}
if(point != 2)
continue;
int f1, f2;
f1 = (a*B.p[B.n/2].x + b*B.p[B.n/2].y + c) < eps;
f2 = (a*xi + b*yi + c) < eps;
//print(B);
//print(C);
if(f1 == f2 && point) {// same side
//puts("B side");
A = B;
} else {
//puts("C side");
A = C;
}
while(fabs(A.p[A.n-1].x-A.p[0].x) < eps &&
fabs(A.p[A.n-1].y-A.p[0].y) < eps)
A.n--;
//print(A);
}
printf("Case #%d: %.3lf\n", ++cases, calcArea(A));
}
return 0;
}