UVA 137 Polygons

求两个凸多边形减去公共部分后的面积,半平面交求凸包交即可

最后一行要输出换行,要不会WA

#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <queue>
#include <stack>
#include <climits>

using namespace std;

const int MAX = 1100;
struct point {double x,y;};
struct line { point a,b; double ang;};
point p[MAX],s[MAX];
line ln[MAX*2],deq[MAX*2];
const double eps = 1e-6;
bool dy(double x,double y)	{	return x > y + eps;}	// x > y 
bool xy(double x,double y)	{	return x < y - eps;}	// x < y 
bool dyd(double x,double y)	{ 	return x > y - eps;}	// x >= y 
bool xyd(double x,double y)	{	return x < y + eps;} 	// x <= y 
bool dd(double x,double y) 	{	return fabs( x - y ) < eps;}  // x == y
double crossProduct(point a,point b,point c)//向量 ac 在 ab 的方向 
{
	return (c.x - a.x)*(b.y - a.y) - (b.x - a.x)*(c.y - a.y);
}
bool parallel(line u,line v)
{
	return dd( (u.a.x - u.b.x)*(v.a.y - v.b.y) - (v.a.x - v.b.x)*(u.a.y - u.b.y) , 0.0 );
}
point l2l_inst_p(line l1,line l2)
{
	point ans = l1.a;
	double t = ((l1.a.x - l2.a.x)*(l2.a.y - l2.b.y) - (l1.a.y - l2.a.y)*(l2.a.x - l2.b.x))/
			   ((l1.a.x - l1.b.x)*(l2.a.y - l2.b.y) - (l1.a.y - l1.b.y)*(l2.a.x - l2.b.x));
	ans.x += (l1.b.x - l1.a.x)*t;
	ans.y += (l1.b.y - l1.a.y)*t;
	return ans;
}
bool equal_ang(line a,line b)	// 第一次unique的比较函数 
{
	return dd(a.ang,b.ang);
}
bool cmphp(line a,line b)	// 排序的比较函数 
{
	if( dd(a.ang,b.ang) ) return xy(crossProduct(b.a,b.b,a.a),0.0);
	return xy(a.ang,b.ang);
}
bool equal_p(point a,point b)//第二次unique的比较函数 
{
	return dd(a.x,b.x) && dd(a.y,b.y);
}
void makeline_hp(point a,point b,line &l) // 线段(向量ab)左侧区域有效 
{
	l.a = a; l.b = b;
	l.ang = atan2(a.y - b.y,a.x - b.x);	// 如果是右侧区域,改成b.y - a.y,b.x - a.x 
}
void inst_hp_nlogn(line *ln,int n,point *s,int &len)
{
	len = 0;
	sort(ln,ln+n,cmphp);
	n = unique(ln,ln+n,equal_ang) - ln;
	int bot = 0,top = 1;
	deq[0] = ln[0]; deq[1] = ln[1];
	for(int i=2; i<n; i++)
	{
		if( parallel(deq[top],deq[top-1]) || parallel(deq[bot],deq[bot+1]) )
			return ;
		while( bot < top && dy(crossProduct(ln[i].a,ln[i].b,
			l2l_inst_p(deq[top],deq[top-1])),0.0) )
			top--;
		while( bot < top && dy(crossProduct(ln[i].a,ln[i].b,
			l2l_inst_p(deq[bot],deq[bot+1])),0.0) )
			bot++;
		deq[++top] = ln[i];
	}
	while( bot < top && dy(crossProduct(deq[bot].a,deq[bot].b,
		l2l_inst_p(deq[top],deq[top-1])),0.0) )	top--;
	while( bot < top && dy(crossProduct(deq[top].a,deq[top].b,
		l2l_inst_p(deq[bot],deq[bot+1])),0.0) )	bot++;
	if( top <= bot + 1 ) return ;
	
	for(int i=bot; i<top; i++)
		s[len++] = l2l_inst_p(deq[i],deq[i+1]);
	if( bot < top + 1 ) s[len++] = l2l_inst_p(deq[bot],deq[top]);
	len = unique(s,s+len,equal_p) - s;
} 
double area_polygon(point p[],int n)
{
	if( n < 3 ) return 0.0; 
	double s = 0.0;
	for(int i=0; i<n; i++)
		s += p[(i+1)%n].y * p[i].x - p[(i+1)%n].x * p[i].y;
	return fabs(s/2.0);
}
int main()
{
	int n,len,m;

	while ( ~scanf("%d",&n) && n )
	{
		for(int i=0; i<n; i++)
			scanf("%lf %lf",&p[i].x,&p[i].y);
		p[n] = p[0];
		double a1 = area_polygon(p,n);
		for(int i=0; i<n; i++)
			makeline_hp(p[i+1],p[i],ln[i]);
		
		scanf("%d",&m);
		for(int i=0; i<m; i++)
			scanf("%lf%lf",&p[i].x,&p[i].y);
		double a2 = area_polygon(p,m);
		p[m] = p[0];
		for(int i=0; i<m; i++)
			makeline_hp(p[i+1],p[i],ln[i+n]);
	
		n += m;
		inst_hp_nlogn(ln,n,s,len);
		double area = a1 + a2 - 2*area_polygon(s,len);
		printf("%8.2lf",area);
	}
	printf("\n");
return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值