题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1632
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Problem Description
Given two convex polygons, they may or may not overlap. If they do overlap, they will do so to differing degrees and in different ways. Write a program that will read in the coordinates of the corners of two convex polygons and calculate the `exclusive or' of the two areas, that is the area that is bounded by exactly one of the polygons. The desired area is shaded in the following diagram:
Input
Input will consist of pairs of lines each containing the number of vertices of the polygon, followed by that many pairs of integers representing the x,y coordinates of the corners in a clockwise direction. All the coordinates will be positive integers less than 100. For each pair of polygons (pair of lines in the data file), your program should print out the desired area correct to two decimal places. The input will end with a line containing a zero (0).
Output
Output will consist of a single line containing the desired area written as a succession of eight (8) digit fields with two (2) digits after the decimal point. There will not be enough cases to need more than one line.
Sample Input
3 5 5 8 1 2 3
3 5 5 8 1 2 3
4 1 2 1 4 5 4 5 2
6 6 3 8 2 8 1 4 1 4 2 5 3
0
Sample Output
0.00
13.50
Problem solving report:
Description: 求出仅存在其中一个多边形的区域面积。
Problem solving: 利用半平面交求出重叠的面积,然后用总面积减去重叠面积的二倍就是答案。
Accepted Code:
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5e4 + 5;
const double eps = 1e-8;
typedef struct point {
double x, y;
}vect;
struct line {
vect p;
point u, v;
bool operator < (const line& s) const {
return atan2(s.p.y, s.p.x) > atan2(p.y, p.x);
}
}Sline[MAXN];
point p1[MAXN], p2[MAXN];
vect operator - (const point& a, const point& b) {
return (vect){a.x - b.x, a.y - b.y};
}
int pnz(double x) {
return x < -eps ? -1 : x > eps ? 1 : 0;
}
double Cross(const vect& a, const vect& b) {
return a.x * b.y - a.y * b.x;
}
bool Onleft(const point& p, const line& l) {
return pnz(Cross(l.p, p - l.u)) > 0;
}
point Inter(const line& a, const line& b) {
double t = Cross(b.p, a.u - b.u) / Cross(a.p, b.p);
return (point){a.u.x + t * a.p.x, a.u.y + t * a.p.y};
}
double Area(point p[], int n) {
double area = 0;
for (int i = 1; i < n - 1; i++)
area += Cross(p[i] - p[0], p[i + 1] - p[0]);
return area / 2;
}
double Halfplane(int n) {
sort(Sline, Sline + n);
int Q[n] = {0};
point Spt[n];
int l = 0, r = 0;
for (int i = 1; i < n; i++) {
while (l < r && !Onleft(Spt[r - 1], Sline[i]))
r--;
while (l < r && !Onleft(Spt[l], Sline[i]))
l++;
Q[++r] = i;
if (!pnz(Cross(Sline[i].p, Sline[Q[r - 1]].p))) {
r--;
if (Onleft(Sline[i].u, Sline[Q[r]]))
Q[r] = i;
}
else Spt[r - 1] = Inter(Sline[Q[r]], Sline[Q[r - 1]]);
}
while (l < r && !Onleft(Spt[r - 1], Sline[Q[l]]))
r--;
while (l < r && !Onleft(Spt[l], Sline[Q[r]]))
l++;
if (r - l <= 1)
return 0;
Spt[r] = Inter(Sline[Q[l]], Sline[Q[r]]);
return Area(Spt + l, r - l + 1);
}
int main() {
int n, m;
while (scanf("%d", &n), n) {
for (int i = n - 1; i >= 0; i--)
scanf("%lf%lf", &p1[i].x, &p1[i].y);
for (int i = 0; i < n; i++) {
int j = (i + 1) % n;
Sline[i] = (line){p1[j] - p1[i], p1[i], p1[j]};
}
scanf("%d", &m);
for (int i = m - 1; i >= 0; i--)
scanf("%lf%lf", &p2[i].x, &p2[i].y);
for (int i = 0; i < m; i++) {
int j = (i + 1) % m;
Sline[i + n] = (line){p2[j] - p2[i], p2[i], p2[j]};
}
printf("%8.2f", Area(p1, n) + Area(p2, m) - 2 * Halfplane(n + m));
}
printf("\n");
return 0;
}