POJ2451Uyuw's Concert

思路:刚开始没看懂题意,其实和求多边形的核类似,这是求半平面的交。开始我感觉用复数表示点,很不习惯,以前从没用过。

poing a; 然后这样给a赋值a.imag() = 0;用C++提交时就一直CE,然后问冰哥,他说在他的DEV c++上有警告,然后我就改为初始化成员列表

然后就AC啦,还是挺兴奋的!

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <complex>
#include <deque>
#include <vector>
using namespace std;
const double eps = 1e-10;
const double maxn = 20100;
typedef complex<double> point;
//2451	Accepted	3344K	704MS	C++	3383B	2013-06-04 19:03:55
typedef pair<point, point> halfplane;
vector <halfplane> term(maxn*4);//全局变量保存开始的半平面。

point operator + (const point &a, const point b) {
    return point(a.real()+b.real(), a.imag()+b.imag());
}
point operator - (const point &a, const point b) {
    return point(a.real()-b.real(), a.imag()-b.imag());
}
inline int sgn(double n) {
    return fabs(n)< eps ? 0 : (n<0 ? -1 : 1);
}
inline double cross(point a, point b) {
    return (conj(a)*b).imag();
}
inline double dot(point a, point b) {
    return (conj(a)*b).real();
}
//点a在半平面的左侧或在半平面上。
inline double satisfy(point a, halfplane p) {
    return sgn(cross(a-p.first, p.second-p.first))<=0;
}
//求半平面交点.
point crosspoint(const halfplane &a, const halfplane &b) {
    double k = cross(b.first-b.second, a.first-b.second);
    k = k / (k-cross(b.first-b.second, a.second-b.second));
    return a.first + (a.second - a.first)*k;
}
//对给出的半平面排序,arg的范围(-PI, PI] 弧度表示。
bool cmp(const halfplane &a, const halfplane &b) {
    int res = sgn(arg(a.second-a.first) - arg(b.second - b.first));
    return res == 0 ? satisfy(a.first, b) : res < 0;
}

vector<point> halfplane_intersection(vector<halfplane> v) {
    sort(v.begin(), v.end(), cmp);
    deque<halfplane> q;
    deque<point> ans;
    q.clear();
    ans.clear();
    q.push_back(v[0]);
    for(int i = 1; i < int(v.size()); i++) {
        if(sgn(arg(v[i].second - v[i].first) - arg(v[i-1].second-v[i-1].first))==0)
            continue;
        while(ans.size()>0 && !satisfy(ans.back(), v[i])) {
            ans.pop_back();
            q.pop_back();
        }
        while(ans.size()>0 && !satisfy(ans.front(), v[i])) {
            ans.pop_front();
            q.pop_front();
        }
        ans.push_back(crosspoint(q.back(), v[i]));
        q.push_back(v[i]);
    }
    while(ans.size()>0 && !satisfy(ans.back(), q.front())) {
        ans.pop_back();
        q.pop_back();
    }
    while(ans.size()>0 && !satisfy(ans.front(), q.back())) {
        ans.pop_front();
        q.pop_back();
    }
    ans.push_back(crosspoint(q.back(), q.front()));
    return vector<point>(ans.begin(), ans.end());
}
//求多边形面积。
double get_area(vector<point> v) {
    int Size = v.size();
    double area = 0;
    for(int i = 1; i < Size-1; i++) {
        area += cross(v[i]-v[0], v[i+1]-v[0]);
    }
    return area/2;
}
//用成员初始化来初始化平面
void init() {
    term.clear();
    point a(0,0), b(10000, 0), c(10000, 10000), d(0, 10000);
    term.push_back(halfplane(a, b));
    term.push_back(halfplane(b, c));
    term.push_back(halfplane(c, d));
    term.push_back(halfplane(d, a));
}

int main()
{
    int n;
    double a, b, c, d;    //how many halfplane;
    while(scanf("%d", &n) != EOF) {
        init();
        for(int i = 0; i < n; i++) {
            scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
            halfplane tmp(point(a,b), point(c,d));//初始化
            term.push_back(tmp);
        }
        /*
        这样就一顿CE.
        for(int i = 0; i < n; i++) {
            scanf("%lf%lf%lf%lf", &a, &b, &c, &d);
            tmp.first.real() = a;
            tmp.first.imag() = b;
            tmp.second.real() = c;
            tmp.second.imag() = d;
            term.push_back(tmp);
        }
        */
        vector <point> result = halfplane_intersection(term);
        double res = get_area(result);
        printf("%.1lf\n", res);
        result.clear();
    }
    return 0;
}

/**
input:
3
10000 10000 0 5000
10000 5000 5000 10000
0 5000 5000 0
7
1 1 5 1
5 1 5 4
5 4 1 6
1 6 1 1
1 2 2 1
5 4 1 4
5 4 1 2
output:
54166666.7
7.5
**/

你可能感兴趣的:(POJ2451Uyuw's Concert)