半平面交总结and模板

博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/40859973

这两天刷了POJ上几道半平面交,对半平面交有了初步的体会,感觉半平面交还是个挺实用的知识点。

半平面交主要是看的ZZY的国家队论文,他提出的是一种O(n×log(n))的排序增量法。

附论文地址: 算法合集之《半平面交的新算法及其实用价值》

POJ 3335 Rotating Scoreboard

题目大意:

World finals 要开始了,比赛场地是一个多边形,裁判跟教练坐在多边形的边上,问场地里是不是存在一个区域使得这个区域内的每个点都能看到多边形边上的计分板。

解题思路:

很单纯的判断多边形的核是不是存在。

POJ 1474 Video Surveillance

题目大意:

一个360度摄像头,给你一个多边形,问多边形中是否存在一个区域,将摄像头放进去可以监控整个多边形区域。

解题思路:

同样的半平面交判断多边形是否存在核。

POJ 3130 How I Mathematician Wonder What You Are!

题目大意:

给出星型的定义:一个多边形F是星形的条件是有一点C∈F,任意点P∈F,线段CP都在多边形F内。

给出一个多边形,判断他是不是一个星型。

解题思路:

一样的求多边形的核是否存在。

POJ 1279 Art Gallery

题目大意:

给出一个画廊(不一定是凸多边形),找到一块区域,使得这块区域内的每个点都能看到整个画廊。求出这块区域的面积。

解题思路:

半平面交求多边形的核,需要求核的面积。

POJ 2451 Uyuw‘s Concert

题目大意:

在一个10000*10000的正方形内举办演唱会,中间会有一些警戒线,舞台只能布置在所有警戒线的左侧,给定一些线段,问最后舞台的面积是多少。

解题思路:

这是zzy当初为他半平面交排序增量法而出的一个题,但是后来POJ改过数据,所以O(n*n)的算法也是可以过去的。

其实还是一个半平面交,求交出来的面积的问题。

半平面交的题就做了差不多这些,主要还是看出来题目类型是求半平面交就可以了,剩下的就好说了。

由于题目都差不多,代码没有太大的变化,所以就只贴一个代码了。

POJ 2451 的AC代码,可以当做模板来用了,当时还因为数组开小了而WA了10多遍。。。。。。为什么不给我返回个RE!!!

#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
const double eps = 1e-8;
const int maxn = 20010;

int tail, head, it;
struct Point {
    double x, y;
} P[maxn];
struct Line {
    Point a, b;
    double angle;
    void getAngle() {angle = atan2(b.y-a.y, b.x-a.x);}
} L[maxn], deq[maxn];

int dcmp(double x) {
    return x < -eps ? -1 : x > eps;
}
double xmult(Point a, Point b, Point c) {
    return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x);
}
bool cmp(Line u, Line v) {
    int d = dcmp(u.angle-v.angle);
    if(d) return d > 0;
    return dcmp(xmult(u.a, v.a, v.b)) > 0;
    ///Clockwise:大于0取向量左半部分为半平面,小于0,取右半部分
}
Point intersection(Line u, Line v)
{
    Point ret = u.a;
    double t = ((u.a.x-v.a.x)*(v.a.y-v.b.y)
               -(u.a.y-v.a.y)*(v.a.x-v.b.x))
             / ((u.a.x-u.b.x)*(v.a.y-v.b.y)
               -(u.a.y-u.b.y)*(v.a.x-v.b.x));
    ret.x += (u.b.x-u.a.x)*t, ret.y += (u.b.y-u.a.y)*t;
    return ret;
}
bool judge(Line l1, Line l2, Line l3) {
    Point p = intersection(l2, l3);
    return dcmp(xmult(p, l1.a, l1.b)) < 0;
    ///Clockwise:大于小于符号与上面cmp()中注释处相反
}
void HPI(Line L[], int n){
    sort(L, L+n, cmp);
    int tmp = 1;
    for(int i = 1; i < n; ++i) {
        if(dcmp(L[i].angle-L[tmp-1].angle) != 0) {
            L[tmp++] = L[i];
        }
    }
    n = tmp;
    deq[0] = L[0], deq[1] = L[1];
    head = 0, tail = 1;
    for(int i = 2; i < n; ++i) {
        while(head < tail && judge(L[i], deq[tail-1], deq[tail]))
            tail--;
        while(head < tail && judge(L[i], deq[head+1], deq[head]))
            head++;
        deq[++tail] = L[i];
    }
    while(head < tail && judge(deq[head], deq[tail-1], deq[tail]))
        tail--;
    while(head < tail && judge(deq[tail], deq[head+1], deq[head]))
        head++;
    if(head == tail) return ;
    it = 0;
    for(int i = head; i < tail; ++i) {
        P[it++] = intersection(deq[i], deq[i+1]);
    }
    if(tail > head+1) {
        P[it++] = intersection(deq[head], deq[tail]);
    }
}
double getArea(Point p[], int n) {
    double area = 0;
    for(int i = 1; i < n-1; ++i) {
        area += xmult(P[0], P[i], P[i+1]);
    }
    return fabs(area)/2.0;
}

int main()
{
    int n;
    while(~scanf("%d", &n)) {
        n += 4;
        L[0] = (Line){(Point){0, 10000}, (Point){0, 0}};
        L[1] = (Line){(Point){10000, 10000}, (Point){0, 10000}};
        L[2] = (Line){(Point){10000, 0}, (Point){10000, 10000}};
        L[3] = (Line){(Point){0, 0}, (Point){10000, 0}};
        L[0].getAngle(), L[1].getAngle(), L[2].getAngle(), L[3].getAngle();
        for(int i = 4; i < n; ++i) {
            scanf("%lf%lf%lf%lf", &L[i].a.x, &L[i].a.y, &L[i].b.x, &L[i].b.y);
            L[i].getAngle();
        }
        HPI(L, n);
        printf("%.1f\n", getArea(P, it));
    }

    return 0;
}

时间: 2024-10-09 13:20:03

半平面交总结and模板的相关文章

半平面交模板

摘自http://blog.csdn.net/accry/article/details/6070621 首先解决问题:什么是半平面? 顾名思义,半平面就是指平面的一半,我们知道,一条直线可以将平面分为两个部分,那么这两个部分就叫做两个半平面. 然后,半平面怎么表示呢? 二维坐标系下,直线可以表示为ax + by + c = 0,那么两个半平面则可以表示为ax + by + c >= 0 和ax + by + c < 0,这就是半平面的表示方法. 还有,半平面的交是神马玩意? 其实就是一个方程

半平面交 模板 poj 3335 poj 3130 poj 1474 判断半平面交是否为空集

半平面交模板 const double pi= acos(-1.0); #define arc(x) (x / 180 * pi) const double EPS = 1e-8; const int Max_N = 105; struct Point{ double x,y; Point(){} Point(double x, double y):x(x),y(y){} Point operator - (Point p){ return Point(x- p.x , y - p.y ) ;

POJ 3525 /// 半平面交 模板

题目大意: 给定n,接下来n行逆时针给定小岛的n个顶点 输出岛内离海最远的点与海的距离 半平面交模板题 将整个小岛视为由许多半平面围成 那么以相同的比例缩小这些半平面 一直到缩小到一个点时 那个点就是离海最远的点 #include <cstdio> #include <cmath> #include <vector> #include <algorithm> using namespace std; const double eps=1e-10; doubl

[模板] 计算几何2: 自适应Simpson/凸包/半平面交/旋转卡壳/闵可夫斯基和

//to update 一些基本的定义在这里: [模板] 计算几何1(基础): 点/向量/线/圆/多边形/其他运算 自适应Simpson 凸包 Andrew 算法, 即分别求上, 下凸包. 时间复杂度 \(O(n \log n)\). struct tvec{db x,y;}; il int dcmp(db a){return fabs(a)<=eps?0:(a>0?1:-1);} il db p2(db a){return a*a;} il db gougu1(db a,db b){retu

半平面交模板 HDU 1469

题意就是要判断一个多边形是否存在核. 我们可以把沿着顺时针方向走这个多边形,对于每个边向量,我们取其右边的半平面,判断交是否为空即可. 对于半平面交算法,我只理解了O(n^2)的算法,大概就是用向量去切割多边形,对于O(nlogn)的算法,我从网上各种搜集以及参考了蓝书的实现,给出了一份能看的代码. O(n^2) 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<cmat

bzoj 2618【半平面交模板】

#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; const int N=505; int d,b,n,m; struct dian { double x,y; dian(double X=0,double Y=0) { x=X,y=Y; } dian operator + (const dian &a) const

Rotating Scoreboard(半平面交模板题)

Rotating Scoreboard http://poj.org/problem?id=3335 Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8506   Accepted: 3357 Description This year, ACM/ICPC World finals will be held in a hall in form of a simple polygon. The coaches and spe

【模板】凸包向内推进求不严格的半平面交——poj3384

想不明白这题写严格的半平面交为什么会错 /* 凸包所有边向内推进r */ #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<algorithm> #include<queue> using namespace std; #define N 205 typedef double db;

poj 1279 半平面交核面积

Art Gallery Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6668   Accepted: 2725 Description The art galleries of the new and very futuristic building of the Center for Balkan Cooperation have the form of polygons (not necessarily conve