POJ 1279 Art Gallery (半平面交求内核面积)

来源:互联网 发布:unity3d扫描生成模型 编辑:程序博客网 时间:2024/06/10 14:53


Art Gallery
Time Limit: 1000MS Memory Limit: 10000KTotal Submissions: 7508 Accepted: 2996

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

170 04 44 79 713 -18 -64 -4

Sample Output

80.00

Source


题意:求内核面积

代码:

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>using namespace std;const double eps = 1e-8;int sgn(double x){    if(fabs(x) < eps) return 0;    if(x < 0) return -1;    return 1;}struct Point{    double x, y;    Point(double xx = 0, double yy = 0) : x(xx), y(yy){} //这里一定要 赋初值为0,要不编译错误。。    Point operator - (const Point &b) const    {        return Point(x-b.x, y-b.y);    }    double operator ^ (const Point &b) const    {        return x*b.y-y*b.x;    }    double operator *(const Point &b) const    {        return x*b.x + y*b.y;    }};struct Line{    Point s, e;    double k;    Line(){}    Line(Point ss, Point ee)    {        s = ss; e = ee;        k = atan2(e.y-s.y, e.x-s.x);  //斜率    }    Point operator &(const Line &b) const    {        Point res = s;        double t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));        res.x += (e.x-s.x)*t;        res.y += (e.y-s.y)*t;        return res;    }};int HPIcmp(Line a, Line b)  //排序。。{    if(fabs(a.k - b.k) > eps) return a.k < b.k;    return ((a.s-b.s)^(b.e-b.s)) < 0;}Line Q[1510];void HPI(Line line[], int n, Point res[], int &resn) //半平面。。{    int tot = n;    sort(line, line+n, HPIcmp);    tot = 1;    for(int i = 1; i < n; i++)    {        if(fabs(line[i].k - line[i-1].k) > eps)  //防止有相同线段吧            line[tot++] = line[i];    }    int head = 0, tail = 1;    Q[0] = line[0];    Q[1] = line[1];    resn = 0;    for(int i = 2; i < tot; i++)    {        if(fabs((Q[tail].e-Q[tail].s) ^ (Q[tail-1].e-Q[tail-1].s)) < eps ||           fabs((Q[head].e-Q[head].s) ^ (Q[head+1].e-Q[head+1].s)) < eps)            return;        while(head < tail && (((Q[tail]&Q[tail-1])-line[i].s)^(line[i].e-line[i].s)) > eps)            tail--;        while(head < tail && (((Q[head]&Q[head+1])-line[i].s)^(line[i].e-line[i].s)) > eps)            head++;        Q[++tail] = line[i];    }     while(head < tail && (((Q[tail]&Q[tail-1])-Q[head].s)^(Q[head].e-Q[head].s)) > eps)        tail--;    while(head < tail && (((Q[head]&Q[head-1])-Q[tail].s)^(Q[tail].e-Q[tail].s)) > eps)        head++;    if(tail <= head+1) return;    for(int i = head; i < tail; i++)        res[resn++] = Q[i]&Q[i+1]; //这个数组里都是内核吧。。    if(head < tail-1)        res[resn++] = Q[head]&Q[tail];}double CalcArea(Point p[], int n)  //求面积{    double res = 0;    for(int i = 0; i < n; i++)        res += (p[i]^p[(i+1)%n])/2;    return res;}Point p[1510];Line line[1510];int main(){    int t, ca = 0;    cin >> t;    while(t--)    {        int n;        scanf("%d", &n);        for(int i = 0; i < n; i++)            scanf("%lf%lf", &p[i].x, &p[i].y);        if(CalcArea(p, n) < 0)            reverse(p, p+n);        for(int i = 0; i < n; i++)            line[i] = Line(p[i], p[(i+1)%n]);        int resn;        HPI(line, n, p, resn);        printf("%.2f\n", CalcArea(p, resn));  //不知道为啥还是穿入的p,只是把n改成resn了    }    return 0;}


0 0