您的位置:首页 > 其它

POJ 2451 Uyuw's Concert (半平面交)

2017-05-11 16:04 471 查看
题目传送门

题目大意 && 做法

半平面交的模板题,要求nlogn的算法。

需要注意的是atan2的精度很差,排序重载<(cmp)时不要用eps比较,否则会WA。

直接上模板。

代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#define N 20010
#define Eps 1e-10
#define Edge 10000

using namespace std;

int n, cnt;

struct Point{
double x, y;
Point() {}
Point(double _x, double _y):x(_x), y(_y) {}
friend Point operator + (Point A, Point B){return Point(A.x + B.x, A.y + B.y);}
friend Point operator - (Point A, Point B){return Point(A.x - B.x, A.y - B.y);}
friend Point operator * (double A, Point B){return Point(A * B.x, A * B.y);}
friend Point operator / (Point A, double B){return Point(A.x / B, A.y / B);}
}Poly
, p
;

double Dot(Point A, Point B){return A.x * B.x + A.y * B.y;}
double Det(Point A, Point B){return A.x * B.y - A.y * B.x;}

struct Line{
Point P, v;//点向式
double ang;
Line() {}
Line(Point _P, Point _v):P(_P), v(_v) {ang = atan2(_v.y, _v.x);}
bool operator < (const Line& l) const{return ang < l.ang;}//注意这里
}L
, q
;

bool Onleft(Point A, Line B){
return Det(A - B.P, B.v) < -Eps;
}

Point Cross(Line A, Line B){
Point p1 = A.P, q1 = A.P + A.v;
Point p2 = B.P, q2 = B.P + B.v;
double x = Det(p2 - p1, q2 - p1), y = Det(q2 - q1, p2 - q1);
return (x * q1 + y * p1) / (x + y);
}

void HalfplaneI(){
sort(L+1, L+n+1);//按极角排序

int head, tail;
q[head = tail = 0] = L[1];//双端队列
for(int i = 2; i <= n; i++){
while(head < tail && !Onleft(p[tail-1], L[i]))  tail --;
while(head < tail && !Onleft(p[head], L[i]))  head ++;//注意顺序不能换
q[++tail] = L[i];
if(fabs(Det(q[tail].v, q[tail-1].v)) < Eps){
tail --;
if(Onleft(L[i].P, q[tail]))  q[tail] = L[i];
}//两向量平行且同向要取内侧的那个
if(head < tail)  p[tail-1] = Cross(q[tail-1], q[tail]);
}
while(head < tail && !Onleft(p[tail-1], q[head]))  tail --;//删除无用平面
if(tail - head <= 1)  return;//空集
p[tail] = Cross(q[tail], q[head]);//头尾相交

cnt = 0;
for(int i = head; i <= tail; i++)  Poly[++cnt] = p[i];
}

double Get_S(){
Poly[cnt+1] = Poly[1];
double S = 0.00;
for(int i = 1; i <= cnt; i++)
S += Det(Poly[i], Poly[i+1]);
return S / 2.00;
}

int main(){
scanf("%d", &n);

double x1, y1, x2, y2;
for(int i = 1; i <= n; i++){
scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
L[i] = Line(Point(x1, y1), Point(x2 - x1, y2 - y1));
}

L[++n] = Line(Point(0, 0), Point(Edge, 0));
L[++n] = Line(Point(0, Edge), Point(0, -Edge));
L[++n] = Line(Point(Edge, 0), Point(0, Edge));
L[++n] = Line(Point(Edge, Edge), Point(-Edge, 0));//按题意加边框

HalfplaneI();

printf("%.1lf\n", Get_S());

return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: