LA 2512 —— Art Gallery(半平面交)

题目:Art Gallery

题意:在一个建筑物里面要放置一个监控,使得能监控到建筑物里所有地方,问能放置监控的面积有多大。

简单的半平面交,直接套模板然后求面积即可,模板是参考《训练指南》的。

输入我是当它是顺时针(分析第一个样例。。。),好像我来回读了几遍题目都没get到点输入顺序的信息 = = ,但是如果没顺序感觉又确定不了建筑物。。。但至少按照顺时针是能AC的。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const double eps = 1e-8;
const int N = 2001;
struct Point{
	double x, y;
	Point(){}
	Point(double x, double y):x(x),y(y){}
};
typedef Point Vector;
Vector operator + (Vector A, Vector B){
	return Vector(A.x+B.x, A.y+B.y);
}
Vector operator - (Point A,  Point B){
	return Vector(A.x-B.x, A.y-B.y);
}
Vector operator * (Vector A, double a){
	return Vector(A.x*a, A.y*a);
}
Vector operator / (Vector A, double a){
	return Vector(A.x/a, A.y/a);
}
int dcmp(double x){
	if(fabs(x)<eps)	return 0;
	return x<0?-1:1;
}
double Dot(Vector A, Vector B){
	return A.x*B.x + A.y*B.y;
}
double Det(Vector A, Vector B){
	return A.x*B.y - A.y*B.x;
}
struct Line{
	Point P;
	Vector v;
	double ang;
	Line(){}
	Line(Point P, Vector v):P(P),v(v){
		ang = atan2(v.y, v.x);
	}
	bool operator < (const Line &tmp)const{
		return ang < tmp.ang;
	};
};
bool OnLeft(Line L, Point p){
	return Det(L.v, p-L.P) > 0;
}
Point GetIntersection(Line a, Line b){
	Vector u = a.P-b.P;
	double t = Det(b.v, u) / Det(a.v, b.v);
	return a.P+a.v*t;
}
Point pt[N], poly[N];
Line L[N], Q[N];
int t, n;
int HalfPlane(){
	sort(L, L+n);
	int head, tail;
	Q[head=tail=0] = L[0];
	for(int i=1; i<n; i++){
		while(head<tail && !OnLeft(L[i], pt[tail-1]))	tail--;
		while(head<tail && !OnLeft(L[i], pt[head]))	head++;
		Q[++tail] = L[i];
		if(fabs(Det(Q[tail].v, Q[tail-1].v)) < eps){
			tail--;
			if(OnLeft(Q[tail], L[i].P))	Q[tail] = L[i];
		}
		if(head < tail)	pt[tail-1] = GetIntersection(Q[tail-1], Q[tail]);
	}
	while(head < tail && !OnLeft(Q[head], pt[tail-1]))	tail--;
	if(tail - head <= 1)	return 0;
	pt[tail] = GetIntersection(Q[tail], Q[head]);
	int m = 0;
	for(int i=head; i<=tail; i++)	poly[m++] = pt[i];
	return m;
}
double Area(int m){
	double S=0.0;
	for(int i=1; i<m-1; i++){
		S += Det(poly[i]-poly[0], poly[i+1]-poly[0]);
	}
	return fabs(S)*0.5;
}
int main(){
	scanf("%d", &t);
	while(t--){
		scanf("%d", &n);
		for(int i=0; i<n; i++){
			scanf("%lf %lf", &pt[i].x, &pt[i].y);
		}
		pt[n] = pt[0];
		for(int i=0; i<n; i++){
			L[i] = Line(pt[i+1], pt[i]-pt[i+1]);
		}
		int m = HalfPlane();
		printf("%.2lf\n", Area(m));
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值