【半平面交】poj2540 Hotter Colder

来源:互联网 发布:UNetbootin ubuntu 编辑:程序博客网 时间:2024/05/18 16:58

写了三天的半平面交委屈总觉得自己姿势有问题。。



#include <cstdio>#include <iostream>#include <cmath>#include <algorithm> #define eps 1e-8using namespace std;struct Point {    double x, y;    Point(double _x = 0. , double _y = 0. ) : x(_x), y(_y) {};}Ext[65];struct Vector {    Point s, e;    double k, d; // 极角 截距}V[65];int tot = 0;inline int dcmp(double x) { if (x < -eps) return -1; return x > eps; }inline double Cross(double x1, double y1, double x2, double y2){    return x1 * y2 - x2 * y1;}inline double Cross(Point O, Point A, Point B){ // 向量 OA 与 OB 的叉积return (A.x - O.x) * (B.y - O.y) - (B.x - O.x) * (A.y - O.y);  }inline void SetLine(double x1, double y1, double x2, double y2, Vector &v){ // 向量左边为有效平面    v.s = Point(x1, y1); v.e = Point(x2, y2);    v.k = atan2(y2 - y1, x2 - x1);    if (dcmp(x1 - x2)) v.d = Cross(x1, y1, x2, y2) / fabs(x1 - x2);    else v.d = Cross(x1, y1, x2, y2) / fabs(y1 - y2);}inline Point Revolve(double cosA, double sinA, Point A, Point B){ // 将向量 AB 逆时针旋转角度A    Point B_;    B_.x = (B.x - A.x) * cosA - (B.y - A.y) * sinA + A.x;    B_.y = (B.x - A.x) * sinA + (B.y - A.y) * cosA + A.y;    return B_;}inline bool VecCmp(const Vector &a,const Vector &b){    if (dcmp(a.k - b.k)) return a.k < b.k;    return a.d < b.d;}inline bool Parallel(Vector a, Vector b){ // 向量平行    double u = Cross(a.s.x - a.e.x, a.s.y - a.e.y, b.s.x - b.e.x, b.s.y - b.e.y);    return !dcmp(u);}Point CrossPoint(Vector a, Vector b){ // 向量求交点    Point res;    double u = Cross(a.s, a.e, b.s), v = Cross(a.e, a.s, b.e);    res.x = (b.s.x * v + b.e.x * u) / (u + v);    res.y = (b.s.y * v + b.e.y * u) / (u + v);    return res; }inline bool EqualPoint(Point &a, Point &b){    return !dcmp(a.x - b.x) && !dcmp(a.y - b.y);}Vector deq[65];void HalfPanelCross(Vector *v, int &N, Point *p, int &M){    sort(v, v + N, VecCmp); int tn = 1; M = 0;    for (int i = 1; i < N; ++ i) {        if (dcmp(v[i].k - v[i - 1].k)) v[tn ++] = v[i];    }    N = tn; if (N < 3) return;    deq[0] = v[0]; deq[1] = v[1];    int head = 0, tail = 1;    for (int i = 2; i < N; ++ i) {        if (Parallel(deq[tail], deq[tail - 1]) || Parallel(deq[head], deq[head + 1])) return;        while ( head < tail && dcmp( Cross(v[i].s, v[i].e, CrossPoint(deq[tail], deq[tail - 1])) ) < 0 ) -- tail;        while ( head < tail && dcmp( Cross(v[i].s, v[i].e, CrossPoint(deq[head], deq[head + 1])) ) < 0 ) ++ head;        deq[++ tail] = v[i];    }    while ( head < tail && dcmp( Cross(deq[head].s, deq[head].e, CrossPoint(deq[tail], deq[tail - 1])) ) < 0 ) -- tail;    while ( head < tail && dcmp( Cross(deq[tail].s, deq[tail].e, CrossPoint(deq[head], deq[head + 1])) ) < 0 ) ++ head;        if (tail < head + 1) return;    for (int i = head; i < tail; ++ i) {        p[M ++] = CrossPoint(deq[i], deq[i + 1]);    }    p[M ++] = CrossPoint(deq[tail], deq[head]);    M = (int)(unique(p, p + M, EqualPoint) - p);}double PolygonArea(Point *p, int M){    double S = p[0].y * (p[M - 1].x - p[1].x);    for (int i = 1; i < M; ++ i) {        S += p[i].y * (p[i - 1].x - p[(i + 1) % M].x);    }    return fabs(S * 0.5);}int main(){    SetLine(0. , 0. , 10. , 0. , V[tot ++]);    SetLine(0. , 10. , 0. , 0. , V[tot ++]);    SetLine(10. , 10. , 0. , 10. , V[tot ++]);    SetLine(10. , 0. , 10. , 10. , V[tot ++]);        Point Last = Point(0. , 0.), Next, Mid, Temp;    string s; int CntLine = 0;    ios :: sync_with_stdio(false); bool flag = 0;    while (cin >> Next.x >> Next.y >> s) {    if (s == "Same" || flag) { flag = 1; printf("0.00\n"); continue; }        Mid = Point((Last.x + Next.x) * 0.5, (Last.y + Next.y) * 0.5);        if (s == "Colder") Temp = Revolve(0. , 1. , Mid, Next);        else if (s == "Hotter")Temp = Revolve(0. , -1. , Mid, Next);        SetLine(Mid.x, Mid.y, Temp.x, Temp.y, V[tot ++]);                HalfPanelCross(V, tot, Ext, CntLine);                if (CntLine < 3) { flag = 1; printf("0.00\n"); }        else printf("%.2f\n", PolygonArea(Ext, CntLine));        Last = Next;    }        return 0;}


0 0