bzoj2618 [Cqoi2006]凸多边形

[Cqoi2006]凸多边形

Time Limit: 5 Sec Memory Limit: 128 MB

Description

逆时针给出n个凸多边形的顶点坐标,求它们交的面积。例如n=2时,两个凸多边形如下图:

则相交部分的面积为5.233。

Input

第一行有一个整数n,表示凸多边形的个数,以下依次描述各个多边形。第i个多边形的第一行包含一个整数mi,表示多边形的边数,以下mi行每行两个整数,逆时针给出各个顶点的坐标。

Output

输出文件仅包含一个实数,表示相交部分的面积,保留三位小数。

Sample Input

2
6
-2 0
-1 -2
1 -2
2 0
1 2
-1 2
4
0 -3
1 -1
2 2
-1 0

Sample Output

5.233

HINT

100%的数据满足:2<=n<=10,3<=mi<=50,每维坐标为[-1000,1000]内的整数

我会半平面交啦啦啦~~~

半平面交我不用多说,有篇论文写的太好啦! Orz

https://wenku.baidu.com/view/c750720bf78a6529647d53ae.html
(顺面可以学一波外语~嘿嘿嘿~)

我就精心画几张图来表示一下啦~~~


#include<bits/stdc++.h>
using namespace std;
struct vec{
	double x, y;
	vec() {}
	vec(double a, double b) { x = a, y = b; }
	vec operator - (const vec &A){ return vec(x - A.x, y - A.y); }
};
struct Line{
	vec A, B; double polar;
	bool operator < (const Line &A)const{ return polar < A.polar; }
}linL, lpl[505], lpd[505];
const int eps = 1e-8;
vector<Line> L;
vector<vec> ans;
int n, m, l, r;

double cross(vec A, vec B){ return A.x * B.y - A.y * B.x; }
bool onleft(vec A, Line X){ return cross(X.B - X.A, A - X.A) > 0; }

vec inter(Line A, Line B){
	double s1, s2, k; vec ret;
	s1 = cross((A.B - A.A), (B.B - A.A));
	s2 = cross((B.A - A.A), (A.B - A.A));
	k = s2 / (s1 + s2);
	ret.x = B.A.x + k * (B.B.x - B.A.x); ret.y = B.A.y + k * (B.B.y - B.A.y);
	return ret;
}

inline void putit()
{
	int mx; vec p[55]; scanf("%d", &n);
	for(int i = 1; i <= n; ++i){
		scanf("%d", &mx);
		for(int j = 1; j <= mx; ++j) scanf("%lf%lf", &p[j].x, &p[j].y);
		for(int j = 1; j < mx; ++j){
			linL.A = p[j], linL.B = p[j + 1]; 
			linL.polar = atan2(linL.B.x - linL.A.x, linL.B.y - linL.A.y);
			L.push_back(linL);
		}
			linL.A = p[mx], linL.B = p[1]; 
			linL.polar = atan2(linL.B.x - linL.A.x, linL.B.y - linL.A.y);
			L.push_back(linL);		
	}
}

inline void HPI()
{
	sort(L.begin(), L.end());
	int len = L.size() - 1; 
	int siz = 1; lpd[1] = L[0];
	for(int i = 1; i <= len; ++i){
		if(L[i].polar != lpd[siz].polar) { lpd[++siz] = L[i]; continue; }
		if(onleft(L[i].A, lpd[siz])) lpd[siz] = L[i];
	}
	l = 1; r = 2; lpl[1] = lpd[1], lpl[2] = lpd[2];
	for(int i = 3; i <= siz; ++i){
		while(l < r && !onleft(inter(lpl[r], lpl[r - 1]), lpd[i])) r--;
		while(l < r && !onleft(inter(lpl[l], lpl[l + 1]), lpd[i])) l++;
		lpl[++r] = lpd[i];
	}
	while(l < r && !onleft(inter(lpl[r], lpl[r - 1]), lpl[l])) r--;
	while(l < r && !onleft(inter(lpl[l], lpl[l + 1]), lpl[r])) l++;
}

inline void print()
{
	lpl[r + 1] = lpl[l];
	for(int i = l; i <= r; ++i) ans.push_back(inter(lpl[i], lpl[i + 1]));
	if(ans.size() < 3) {printf("0.000"); return;}
	double ret = 0; 	
	ans.push_back(ans[0]);
	int len = ans.size() - 1;
	for(int i = 0; i < len; ++i) 
	ret += cross(ans[i], ans[i + 1]);
	printf("%.3lf", fabs(ret) / 2);
}

int main()
{
	putit();
	HPI();
	print();
	return 0;
}

posted @ 2018-04-15 00:05  沛霖  阅读(198)  评论(0编辑  收藏  举报