[CSU 1812 三角形和矩形] 计算几何

[CSU 1812 三角形和矩形] 计算几何

题目链接:[CSU 1812 三角形和矩形]
题意描述:求三角形和矩形相交面积。已知矩形的四条边和三角形的两条边是与坐标轴平行的。
解题思路:真的是一个裸的模版题。首先,求出三角形的在矩形区域的顶点,矩形在三角形区域的顶点。然后求出所有的交点。这些点构成一个凸包,求凸包面积就OK了。
计算几何太不熟练了,导致这个题目省赛的时候没有时间写出来…

#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

typedef long long LL;

const int MAXN = 20;
const long double eps = 1e-8;

long double X1, X2, X3, X4, Y1, Y2, Y3, Y4, ans;
int sgn(long double x) {
    if(fabs(x) < eps) return 0;
    if(x < 0) return -1;
    else return 1;
}
struct Point {
    long double x, y;
    Point() {}
    Point(long double _x, long double _y) {
        x = _x;
        y = _y;
    }
    Point operator -(const Point &b)const {
        return Point(x - b.x, y - b.y);
    }
    long double operator ^(const Point &b)const {
        return x * b.y - y * b.x;
    }
    long double operator *(const Point &b)const {
        return x * b.x + y * b.y;
    }
    bool operator ==(const Point& b)const {
        return x == b.x && y == b.y;
    }
};
struct Line {
    Point s, e;
    Line() {}
    Line(Point _s, Point _e) {
        s = _s;
        e = _e;
    }
    pair<int, Point> operator &(const Line &b)const {
        Point res = s;
        if(sgn((s - e) ^ (b.s - b.e)) == 0) {
            if(sgn((s - b.e) ^ (b.s - b.e)) == 0)
                return make_pair(0, res); //重合
            else return make_pair(1, res); //平行
        }
        long 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 make_pair(2, res);
    }
};
Point plist[MAXN];
int sz;

long double dist(Point a, Point b) {
    return sqrt((a - b) * (a - b));
}
bool _cmp(Point p1, Point p2) {
    long double tmp = (p1 - plist[0]) ^ (p2 - plist[0]);
    if(sgn(tmp) > 0)return true;
    else if(sgn(tmp) == 0 && sgn(dist(p1, plist[0]) - dist(p2, plist[0])) <= 0)
        return true;
    else return false;
}
long double CalcArea(Point p[], int n) {
    long double res = 0;
    for(int i = 0; i < n; i++)
        res += (p[i] ^ p[(i + 1) % n]);
    return fabs(res / 2);
}
inline bool inRect(Point p) {
    return sgn(p.x - X3) >= 0 && sgn(p.x - X4) <= 0 && sgn(p.y - Y3) >= 0 && sgn(p.y - Y4) <= 0;
}
inline bool inTrig(Point p) {
    Point a(X1, Y1), b(X1, Y2), c(X2, Y1);
    long double s = fabs((a - b) ^ (a - c));
    long double s1 = fabs((p - a) ^ (p - b));
    long double s2 = fabs((p - a) ^ (p - c));
    long double s3 = fabs((p - b) ^ (p - c));
    if(sgn(s1 + s2 + s3 - s) < 0) while(1);
    return sgn(s1 + s2 + s3 - s) == 0;
}
int main() {
    freopen("input.txt", "r", stdin);
    while(cin >> X1 >> Y1 >> X2 >> Y2 >> X3 >> Y3 >> X4 >> Y4) {
        Point trig[3] = {Point(X1, Y1), Point(X1, Y2), Point(X2, Y1)};
        Point rect[4] = {Point(X3, Y3), Point(X3, Y4), Point(X4, Y4), Point(X4, Y3)};
        sz = 0;
        for(int i = 0; i < 3; i++) {
            if(inRect(trig[i])) {
                plist[sz ++] = trig[i];
            }
        }
        for(int i = 0; i < 4; i++) {
            if(inTrig(rect[i])) {
                plist[sz ++] = rect[i];
            }
        }
        Line L1, L2;
        pair<int, Point> ret;
        for(int i = 0; i < 3; i++) {
            L1 = Line(trig[i], trig[(i + 1) % 3]);
            for(int j = 0; j < 4; j++) {
                L2 = Line(rect[j], rect[(j + 1) % 4]);
                ret = L1 & L2;
                if(ret.first == 2) {
                    Point &t = ret.second;
                    if(sgn((t.x - trig[i].x) * (t.x - trig[(i + 1) % 3].x)) <= 0 &&
                            sgn((t.y - trig[i].y) * (t.y - trig[(i + 1) % 3].y)) <= 0 &&
                            sgn((t.x - rect[j].x) * (t.x - rect[(j + 1) % 4].x)) <= 0 &&
                            sgn((t.y - rect[j].y) * (t.y - rect[(j + 1) % 4].y)) <= 0)
                        plist[sz ++] = t;
                }
            }
        }
        sort(plist, plist + sz, _cmp);
        sz = unique(plist, plist + sz) - plist;
        ans = CalcArea(plist, sz);
        cout << fixed << setprecision(8) << ans << endl;
    }
    return 0;
}

你可能感兴趣的:(ACM____数,学)