题目大意:给出N个凸多边形,求这些多边形的面积并。
思路:N只有不到10,乱搞就可以。还有一种更优的解法,似乎只需要O(n^2logn)的时间就可以解决。但是我并不会,想了解的参照:http://wyfcyx.is-programmer.com/posts/80378.html
下面说乱搞的思路。由于都是凸多边形,那么任意一条垂直于x轴的直线在多边形内的区域一定是一条线段(或者什么都没有),那么我们将所有多边形按照梯形进行剖分,求出每个部分的梯形中腰长度并就可以算出总的面积了。
题目网址见:http://oj.jdfz.com.cn:8081/oldoj/problem.php?id=1005
CODE:
#define _CRT_SECURE_NO_WARNINGS
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define MAX 20
#define EPS 1e-8
using namespace std;
#define max(a,b) ((a) > (b) ? (a):(b))
#define min(a,b) ((a) < (b) ? (a):(b))
#define INRANGE(x,y,c) ((c <= y && c >= x) || (c <= x && c >= y))
struct Point{
double x,y;
Point(double _,double __):x(_),y(__) {}
Point() {}
Point operator +(const Point &a)const {
return Point(x + a.x,y + a.y);
}
Point operator -(const Point &a)const {
return Point(x - a.x,y - a.y);
}
Point operator *(double a)const {
return Point(x * a,y * a);
}
void Read() {
scanf("%lf%lf",&x,&y);
}
}temp[1010];
inline double Calc(const Point &p1,const Point &p2)
{
return sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
}
inline double Cross(const Point &p1,const Point &p2)
{
return p1.x * p2.y - p1.y * p2.x;
}
struct Segment{
Point p1,p2,v;
Segment(Point _,Point __,Point ___):p1(_),p2(__),v(___) {}
Segment() {}
bool OnSegment(const Point &p) {
if(p1.x == p2.x) return INRANGE(p1.y,p2.y,p.y);
return INRANGE(p1.x,p2.x,p.x);
}
}*src[MAX][1010],save[MAX * 1010];
int cnt_seg;
struct Interval{
double x,y;
Interval(double _,double __):x(_),y(__) {}
Interval() {}
bool operator <(const Interval &a)const {
if(x == a.x) return y < a.y;
return x < a.x;
}
}interval[MAX * 1010];
inline Point GetIntersection(const Segment &l1,const Segment &l2)
{
Point u = l1.p1 - l2.p1;
double t = Cross(l2.v,u) / Cross(l1.v,l2.v);
return l1.p1 + l1.v * t;
}
inline Segment *MakeSegment(const Point &p1,const Point &p2)
{
save[++cnt_seg] = Segment(p1,p2,p2 - p1);
return &save[cnt_seg];
}
inline Interval GetInterval(Segment *src[],double x)
{
Interval re(0,0);
for(int i = 1; src[i] != NULL; ++i) {
Point intersection = GetIntersection(*src[i],Segment(Point(x,0),Point(x,0),Point(0,1)));
if(src[i]->OnSegment(intersection)) {
if(!re.x) re.x = intersection.y;
else re.y = intersection.y;
}
}
if(re.x > re.y) swap(re.x,re.y);
return re;
}
int cnt;
double divide[1010 * 1010];
int main()
{
cin >> cnt;
for(int points,i = 1; i <= cnt; ++i) {
scanf("%d",&points);
for(int j = 1; j <= points; ++j)
temp[j].Read();
for(int j = 1; j < points; ++j)
src[i][j] = MakeSegment(temp[j],temp[j + 1]);
src[i][points] = MakeSegment(temp[points],temp[1]);
}
int divides = 0;
for(int i = 1; i <= cnt_seg; ++i)
for(int j = i + 1; j <= cnt_seg; ++j) {
if(fabs(Cross(save[i].v,save[j].v)) < EPS) continue;
Point intersection = GetIntersection(save[i],save[j]);
divide[++divides] = intersection.x;
}
sort(divide + 1,divide + divides + 1);
double area = .0;
for(int i = 1; i < divides; ++i) {
double x = (divide[i + 1] + divide[i]) / 2;
int intervals = 0;
for(int j = 1; j <= cnt; ++j)
interval[++intervals] = GetInterval(src[j],x);
sort(interval + 1,interval + intervals + 1);
double now = .0,l = interval[1].x,r = interval[1].y;
for(int j = 2; j <= intervals; ++j)
if(interval[j].x <= r)
r = max(r,interval[j].y);
else {
now += r - l;
l = interval[j].x;
r = interval[j].y;
}
now += r - l;
area += now * (divide[i + 1] - divide[i]);
}
cout << fixed << setprecision(3) << area << endl;
return 0;
}原文地址:http://blog.csdn.net/jiangyuze831/article/details/43950529