POJ 2451 (半平面交 板子题)

来源:互联网 发布:零食店铺推荐知乎 编辑:程序博客网 时间:2024/05/29 19:27

题目链接:点击这里

题意: 给出n个半平面, 求出半平面交和一个矩形的面积交。

检验一发板子.

#include <cstdio>#include <cmath>#include <algorithm>#include <iostream>#include <vector>using namespace std;#define maxn 100005const double eps = 1e-7;const double INF = 1e20;const double pi = acos (-1.0);int dcmp (double x) {    if (fabs (x) < eps) return 0;    return (x < 0 ? -1 : 1);}inline double sqr (double x) {return x*x;}//*************点struct Point {    double x, y;    Point (double _x = 0, double _y = 0):x(_x), y(_y) {}    void input () {scanf ("%lf%lf", &x, &y);}    void output () {printf ("%.2f %.2f\n", x, y);}    bool operator == (const Point &b) const {        return (dcmp (x-b.x) == 0 && dcmp (y-b.y) == 0);    }    bool operator < (const Point &b) const {        return (dcmp (x-b.x) == 0 ? dcmp (y-b.y) < 0 : x < b.x);    }    Point operator + (const Point &b) const {        return Point (x+b.x, y+b.y);    }    Point operator - (const Point &b) const {        return Point (x-b.x, y-b.y);    }    Point operator * (double a) {        return Point (x*a, y*a);    }    Point operator / (double a) {        return Point (x/a, y/a);    }    double len2 () {//返回长度的平方        return sqr (x) + sqr (y);    }    double len () {//返回长度        return sqrt (len2 ());    }    Point change_len (double r) {//转化为长度为r的向量        double l = len ();        if (dcmp (l) == 0) return *this;//零向量返回自身        r /= l;        return Point (x*r, y*r);    }    Point rotate_left () {//顺时针旋转90度        return Point (-y, x);    }    Point rotate_right () {//逆时针旋转90度        return Point (y, -x);    }    Point rotate (Point p, double ang) {//绕点p逆时针旋转ang        Point v = (*this)-p;        double c = cos (ang), s = sin (ang);        return Point (p.x + v.x*c - v.y*s, p.y + v.x*s + v.y*c);    }    Point normal () {//单位法向量        double l = len ();        return Point (-y/l, x/l);    }};double cross (Point a, Point b) {//叉积    return a.x*b.y-a.y*b.x;}double dot (Point a, Point b) {//点积    return a.x*b.x + a.y*b.y;}double dis (Point a, Point b) {//两个点的距离    Point p = b-a; return p.len ();}double rad_degree (double rad) {//弧度转化为角度    return rad/pi*180;}double rad (Point a, Point b) {//两个向量的夹角    return fabs (atan2 (fabs (cross (a, b)), dot (a, b)) );}bool parallel (Point a, Point b) {//向量平行    double p = rad (a, b);    return dcmp (p) == 0 || dcmp (p-pi) == 0;}//************直线 线段struct Line {    Point s, e;//直线的两个点    double k;//极角    Line () {}    Line (Point _s, Point _e) {        s = _s, e = _e;        k = atan2 (e.y - s.y,e.x - s.x);    }    //一个点和倾斜角确定直线    Line (Point p, double ang) {        k = ang;        s = p;        if (dcmp (ang-pi/2) == 0) {            e = s + Point (0, 1);        }        else            e = s + Point (1, tan (ang));    }    void input () {        s.input ();        e.input ();    }    void adjust () {        if (e < s) swap (e, s);    }    double length () {//求线段长度        return dis (s, e);    }    void get_angle () {        k = atan2 (e.y - s.y,e.x - s.x);    }    double angle () {//直线的倾斜角        if (dcmp (k) < 0) k += pi;        if (dcmp (k-pi) == 0) k -= pi;        return k;    }    Point operator &(const Line &b)const {//直线的交点(保证存在)        Point res = s;        double t = (cross (s - b.s, b.s - b.e))/cross (s - e, b.s - b.e);         res.x += (e.x - s.x)*t;        res.y += (e.y - s.y)*t;        return res;    }};double polygon_area (Point *p, int n) {    //n个点    double area = 0;    for (int i = 1; i < n-1; i++) {        area += cross (p[i]-p[0], p[i+1]-p[0]);    }    return area/2;}bool HPIcmp (const Line &a, const Line &b) {    if (fabs(a.k - b.k) > eps)        return a.k < b.k;    return cross (a.s - b.s, b.e - b.s) < 0; }Line Q[maxn];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(cross (Q[tail].e-Q[tail].s, Q[tail-1].e-Q[tail-1].s)) < eps || fabs(cross (Q[head].e-Q[head].s, Q[head+1].e-Q[head+1].s)) < eps)            return;        while(head < tail && (cross ((Q[tail]&Q[tail-1])-line[i].s, line[i].e-line[i].s)) > eps) tail--;        while(head < tail && (cross ((Q[head]&Q[head+1]) - line[i].s, line[i].e-line[i].s)) > eps)        head++;         Q[++tail] = line[i];    }    while(head < tail && (cross ((Q[tail]&Q[tail-1]) - Q[head].s, Q[head].e-Q[head].s)) > eps)        tail--;    while(head < tail && (cross ((Q[head]&Q[head-1]) -Q[tail].s, Q[tail].e-Q[tail].e)) > 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];}int n, m;Point ans[maxn];Line hp[maxn];int main () {    while (cin >> n) {        for (int i = 0; i < n; i++) {            hp[i].input ();            hp[i].get_angle ();        }        hp[n++] = Line (Point (0, 0), Point (10000, 0));        hp[n++] = Line (Point (10000, 0), Point (10000, 10000));        hp[n++] = Line (Point (10000, 10000), Point (0, 10000));        hp[n++] = Line (Point (0, 10000), Point (0, 0));        HPI (hp, n, ans, m);         if (m) {            printf ("%.1f\n", polygon_area (ans, m));        }        else             printf ("0.0\n");    }    return 0;}
0 0