Art Gallery

Time Limit: 1000MS Memory Limit: 10000K

Description

The art galleries of the new and very futuristic building of the Center for Balkan Cooperation have the form of polygons (not necessarily convex). When a big exhibition is organized, watching over all of the pictures is a big security concern. Your task is that for a given gallery to write a program which finds the surface of the area of the floor, from which each point on the walls of the gallery is visible. On the figure 1. a map of a gallery is given in some co-ordinate system. The area wanted is shaded on the figure 2.



Input

The number of tasks T that your program have to solve will be on the first row of the input file. Input data for each task start with an integer N, 5 <= N <= 1500. Each of the next N rows of the input will contain the co-ordinates of a vertex of the polygon ? two integers that fit in 16-bit integer type, separated by a single space. Following the row with the co-ordinates of the last vertex for the task comes the line with the number of vertices for the next test and so on.

Output

For each test you must write on one line the required surface - a number with exactly two digits after the decimal point (the number should be rounded to the second digit after the decimal point).

Sample Input

1

7

0 0

4 4

4 7

9 7

13 -1

8 -6

4 -4

Sample Output

80.00

Source

Southeastern Europe 2002

这又是一道基础的计算几何题,准确的说,这就是求半平面交的裸板,这也是本蒟蒻第一次写半平面交这个东西。这里简单提一下半平面交的求法吧。

首先,我们将所有半平面按照极角排序,然后用类似极角排序求凸包的方法来求半平面交,但区别是求凸包只需要使用一个栈,而现在我们需要维护的是一个双端队列。为什么呢?因为如果我们当前再放入一个半平面,它会对队首和队尾的半平面都产生影响(没懂的可以画个图感受一下)。什么时候我们会从队列中弹出半平面中呢?显然需要判断前两个半平面的交点和该半平面的关系,如果点在半平面右侧就弹出直到弹不动或者队列为空为止。然后实现时会有一些比较烦的细节,但总的来说写起来还是比较愉快的。

我们要注意这道题的一些坑点:首先点可能按顺时针或者逆时针给出,这样的话我们要先按一定顺序求一遍原多边形的面积来调整每个半平面的方向。其次,本蒟蒻在POJ上一直WA,对着其他大佬的代码改也过不了,最后无奈将printf函数中的lf改成了f就过了,这个真的是玄学错误了。

代码如下:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define eps 1.0e-12
#define N 1505
using namespace std;
int t,n,q[N];
struct point{double x,y;}p[N];
struct line{point a,b;double poa;}l[N];
inline point operator-(point a,point b){return point{a.x-b.x,a.y-b.y};}
inline double cross(point a,point b){return a.x*b.y-b.x*a.y;}
inline point across(line a,line b){
    double a1=cross(b.b-a.a,b.a-a.a),a2=cross(b.a-a.b,b.b-a.b);
    return point{(a2*a.a.x+a1*a.b.x)/(a2+a1),(a2*a.a.y+a1*a.b.y)/(a2+a1)};
}
inline bool check(point a,line b){return cross(a-b.a,b.b-b.a)>0;}
inline bool cmp(line a,line b){
    if(fabs(a.poa-b.poa)<eps)return cross(a.b-b.a,b.b-b.a)<0;
    return a.poa<b.poa;
}
inline double solve(){
    sort(l+1,l+n+1,cmp);
    int siz=0,head=1,tail=1;
    for(int i=1;i<=n;++i)
        if(fabs(l[i-1].poa-l[i].poa)>eps)l[++siz]=l[i];
    q[1]=1;
    for(int i=2;i<=siz;++i){
        while(head<tail&&check(across(l[q[tail-1]],l[q[tail]]),l[i]))--tail;
        while(head<tail&&check(across(l[q[head]],l[q[head+1]]),l[i]))++head;
        q[++tail]=i;
    }
    while(head<tail&&check(across(l[q[tail-1]],l[q[tail]]),l[q[head]]))--tail;
    while(head<tail&&check(across(l[q[head]],l[q[head+1]]),l[q[tail]]))++head;
    if(tail-head<=1)return 0.00;
    else{
        for(int i=head;i<tail;++i)p[i-head+1]=across(l[q[i]],l[q[i+1]]);
        p[tail-head+1]=across(l[q[tail]],l[q[head]]);
        double ans=0.0;
        for(int i=1;i<=tail-head;++i)ans+=cross(p[i],p[i+1]);
        ans+=cross(p[tail-head+1],p[1]);
        return ans/2.0;
    }
}
int main(){
    scanf("%d",&t);
    while(t--){
        scanf("%d",&n);
        for(int i=1;i<=n;++i)scanf("%lf%lf",&p[i].x,&p[i].y);
        double area=0.0;
        for(int i=1;i<n;++i){
            l[i].a=p[i],l[i].b=p[i+1];
            area+=cross(p[i],p[i+1]);
        }
        l[n].a=p[n],l[n].b=p[1];
        area+=cross(p[n],p[1]);
        if(area<0.0)for(int i=1;i<=n;++i)swap(l[i].a,l[i].b);
        for(int i=1;i<=n;++i)l[i].poa=atan2(l[i].b.y-l[i].a.y,l[i].b.x-l[i].a.x);
        printf("%.2f\n",solve());
    }
    return 0;
}

2018.07.03 POJ 1279Art Gallery(半平面交)的更多相关文章

  1. 2018.07.03 POJ 2318 TOYS(二分+简单计算几何)

    TOYS Time Limit: 2000MS Memory Limit: 65536K Description Calculate the number of toys that land in e ...

  2. 2018.07.03 POJ 2653 Pick-up sticks(简单计算几何)

    Pick-up sticks Time Limit: 3000MS Memory Limit: 65536K Description Stan has n sticks of various leng ...

  3. 2018.07.03 POJ 3348 Cows(凸包)

    Cows Time Limit: 2000MS Memory Limit: 65536K Description Your friend to the south is interested in b ...

  4. POJ 1279 Art Gallery 半平面交/多边形求核

    http://poj.org/problem?id=1279 顺时针给你一个多边形...求能看到所有点的面积...用半平面对所有边取交即可,模版题 这里的半平面交是O(n^2)的算法...比较逗比.. ...

  5. POJ 1279 Art Gallery 半平面交求多边形核

    第一道半平面交,只会写N^2. 将每条边化作一个不等式,ax+by+c>0,所以要固定顺序,方便求解. 半平面交其实就是对一系列的不等式组进行求解可行解. 如果某点在直线右侧,说明那个点在区域内 ...

  6. poj 3335(半平面交)

    链接:http://poj.org/problem?id=3335     //大牛们常说的测模板题 ------------------------------------------------- ...

  7. POJ 1755 Triathlon [半平面交 线性规划]

    Triathlon Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 6912   Accepted: 1790 Descrip ...

  8. 2018.07.03 BZOJ 1007: [HNOI2008]水平可见直线(简单计算几何)

    1007: [HNOI2008]水平可见直线 Time Limit: 1 Sec Memory Limit: 162 MB Description 在xoy直角坐标平面上有n条直线L1,L2,-Ln, ...

  9. POJ 1279 Art Gallery(半平面交)

    题目链接 回忆了一下,半平面交,整理了一下模版. #include <cstdio> #include <cstring> #include <string> #i ...

随机推荐

  1. C# WEB.API 多图上传

    using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Ne ...

  2. 基于OpenGL编写一个简易的2D渲染框架-10 重构渲染器-Pass

    Pass,渲染通路,一个渲染通路指的是一次像素处理和一次顶点处理,也就是指的是一次绘制.简单来说就是顶点数据在渲染管线中走一遍最后绘制. 渲染粒子系统的粒子时,需要开启 OpenGL 的混合模式,并使 ...

  3. mysql使用一条sql删除多条数据

    使用in delete from course where chour in(55,56,57); course:表名 chour:字段 55,56,57数据

  4. Erlang/OTP:基于Behaviour的回调函数

    原始链接:https://blog.zhustec.me/posts/erlang-otp-1-callback-based-on-behaviour OTP 是什么 OTP 的全称是开源电信平台 ( ...

  5. js数组类型判断与数据类型判断回顾

    判断一个对象是否是数组方法有多种: 一.Array.isArray()函数 在ECMAScript5中可以通过Array.isArray()来做这件事: Array.isArray({}); //fa ...

  6. eclipse中maven多模块项目的创建、提交和检出

    1.创建父项目:maven项目.创建完成后删除src目录:删除项目属性java builder中的src目录. 2.在父项目中创建maven module子项目. 3.修改pom文件,添加依赖,修改g ...

  7. HQL中的Like查询需要注意的地方

    public List getOrgan(String organCode, String organName) {    String hsql;    List list; if (organCo ...

  8. JavaScript eval_r() 函数

    定义和用法 eval_r() 函数可计算某个字符串,并执行其中的的 JavaScript 代码. 语法 eval_r(string) 参数 描述 string 必需.要计算的字符串,其中含有要计算的  ...

  9. IE下设置body{overflow:hidden;}失效Bug

    问题重现: <p>There are no scrollbars on this page in sane browsers</p> html, body, p { margi ...

  10. mysql 新增数据