POJ1279 Art Gallery


Time Limit: 1000MS Memory Limit: 10000K
Total Submissions: 4300 Accepted: 1849

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
思考:求多边形的核,给出的多边形点的顺序可能是逆序也可能是顺序,给出的最大数的范围16-bit integer type。用C++提交AC,用G++提交WA。有时间学习一下两则的不同。

半平面问题的第一题,很兴奋!
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <vector>
#include <complex>
using namespace std;
const int maxn = 2000;
const double inf = 1e5;
const double eps = 1e-10;
//1279	Accepted	348K	0MS	C++	3482B	2013-06-04 09:13:50
struct point {
    double x;
    double y;
    point(){}
    point( double a, double b):x(a), y(b){}
    friend point operator - (const point &a, const point &b) {
        return point(a.x-b.x, a.y-b.y);
    }
};

double det(const point &a, const point &b) {
    return a.x*b.y - a.y*b.x;
}

struct polygon {
    int n;
    point a[maxn];
};
//把直线化为一般式。
struct halfPlane {
    double a, b, c;
    halfPlane(point p, point q) {
        a = q.y - p.y;
        b = p.x - q.x;
        c = det(q, p);
    }
};

struct polygon_convex {
    vector <point> P;
};

double calc(halfPlane &L, point &a) {
    return a.x*L.a + a.y*L.b + L.c;
}

point Intersect(point &a, point &b, halfPlane &L) {
    point res;
    double t1 = calc(L, a), t2 = calc(L,  b);
    res.x = (t2*a.x - t1*b.x)/(t2-t1);
    res.y = (t2*a.y - t1*b.y)/(t2-t1);
    return res;
}
//将一个凸多边形和一个半平面交。
polygon_convex cut(polygon_convex &a, halfPlane &L) {
    int n = a.P.size();
    polygon_convex res;
    for(int i = 0; i < n; i++) {
        if(calc(L, a.P[i])<-eps) {
            res.P.push_back(a.P[i]);
        }
        else {
            int j;
            j = i - 1;
            if(j < 0) j = n-1;
            if(calc(L, a.P[j])<-eps)
                res.P.push_back(Intersect(a.P[j], a.P[i],L));
            j = i + 1;
            if(j==n) j = 0;
            if(calc(L, a.P[j])<-eps)
                res.P.push_back(Intersect(a.P[i], a.P[j], L));
        }
    }
    return res;
}
//参数为一个多边形, 返回一个凸多边形。
polygon_convex core(polygon &a) {
    polygon_convex res;
    res.P.clear();   //清空容器.
    res.P.push_back(point(-inf, -inf));
    res.P.push_back(point(inf, -inf));
    res.P.push_back(point(inf, inf));
    res.P.push_back(point(-inf, inf));
    int n = a.n;
    if(n==2) {
        halfPlane L(a.a[0], a.a[1]);
        return res = cut(res, L);
    }
    for(int i = 0; i < n ; i++) {
        halfPlane L(a.a[i], a.a[(i+1)%n]);//多边形循环产生n个半平面。
        // printf("%.2lf, %.2lf, %.2lf\n", L.a, L.b, L.c);
        res = cut(res, L);//用产生的半平面调用cut去一次次切割。
    }
    return res;//还回凸多边形.
}

//如果多边形是顺时针给出,则改变方向.
polygon init(polygon v) {
    int n = v.n;
    double area = 0;
    for(int i = 1; i < n-1; i++) {
        area += det(v.a[i]-v.a[0], v.a[i+1]-v.a[0]);
    }
    if(area < 0) {
        polygon temp;
        temp.n = n;
        temp.a[0] = v.a[0];
        for(int i = n-1; i >= 1; i--) {
            temp.a[n-i] = v.a[i];
        }
        return temp;
    }
    return v;
}

double get_area(polygon_convex v) {
    double area = 0;
    int n = v.P.size();
    for(int i = 1; i < n-1; i++) {
        area += det(v.P[i]-v.P[0], v.P[i+1]-v.P[0]);
    }
    return area/2;
}

int main()
{
    polygon v;
    point tmp;
    int T;
    int n;
    scanf("%d", &T);
    while(T--) {
        scanf("%d", &n);
        v.n = 0;
        for(int i = 0; i < n; i++) {
            scanf("%lf%lf", &tmp.x, &tmp.y);
            v.a[i] = tmp;
            v.n++;  //别忘了。
        }
        v = init(v);
        polygon_convex ans = core(v);
        double result = get_area(ans);
        printf("%.2lf\n", result);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值