CSU 1812 三角形和矩形(计算几何,多边形面积交)



代码:

#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <string>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#pragma comment(linker,"/STACK:102400000,102400000")

using namespace std;
#define   MAX           100005
#define   MAXN          1000005
#define   maxnode       205
#define   sigma_size    2
#define   lson          l,m,rt<<1
#define   rson          m+1,r,rt<<1|1
#define   lrt           rt<<1
#define   rrt           rt<<1|1
#define   middle        int m=(r+l)>>1
#define   LL            long long
#define   ull           unsigned long long
#define   mem(x,v)      memset(x,v,sizeof(x))
#define   lowbit(x)     (x&-x)
#define   pii           pair<int,int>
#define   bits(a)       __builtin_popcount(a)
#define   mk            make_pair
#define   limit         10000

//const int    prime = 999983;
const int    INF   = 0x3f3f3f3f;
const LL     INFF  = 0x3f3f;
//const double pi    = acos(-1.0);
const double inf   = 1e18;
const double eps   = 1e-9;
const LL     mod   = 1e9+7;
const ull    mx    = 133333331;

/*****************************************************/
inline void RI(int &x) {
      char c;
      while((c=getchar())<'0' || c>'9');
      x=c-'0';
      while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0';
 }
/*****************************************************/

const int MX = 10+5;
int sgn(double x) {
    if(fabs(x) < eps)return 0;
    if(x < 0)return -1;
    else return 1;
}
struct Point {
    double x, y;
    Point() {}
    Point(double _x, double _y) {
        x = _x; y = _y;
    }
    Point operator -(const Point &b)const {
        return Point(x - b.x, y - b.y);
    }
    double operator ^(const Point &b)const {
        return x * b.y - y * b.x;
    }
    double operator *(const Point &b)const {
        return x * b.x + y * b.y;
    }
    bool operator<(const Point &b) const {
        if(x == b.x) return y < b.y;
        return x < b.x;
    }
};
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);
        }
        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);
    }
} L[MX];
/*l1直线,l2线段*/
bool Seg_inter_line(Line l1, Line l2) {
    return sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e-l1.e) ^ (l1.s - l1.e)) < 0;
}
/*线段是否相交*/
bool inter(Line l1, Line l2) {
    return
        max(l1.s.x, l1.e.x) >= min(l2.s.x, l2.e.x) &&
        max(l2.s.x, l2.e.x) >= min(l1.s.x, l1.e.x) &&
        max(l1.s.y, l1.e.y) >= min(l2.s.y, l2.e.y) &&
        max(l2.s.y, l2.e.y) >= min(l1.s.y, l1.e.y) &&
        sgn((l2.s - l1.e) ^ (l1.s - l1.e)) * sgn((l2.e-l1.e) ^ (l1.s - l1.e)) <= 0 &&
        sgn((l1.s - l2.e) ^ (l2.s - l2.e)) * sgn((l1.e-l2.e) ^ (l2.s - l2.e)) <= 0;
}
bool OnSeg(Point P, Line L) {
    return
        sgn((L.s - P) ^ (L.e-P)) == 0 &&
        sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
        sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}
int inPoly(Point p, Point poly[], int n) {
    int cnt;
    Line ray, side;
    cnt = 0;
    ray.s = p;
    ray.e.y = p.y;
    ray.e.x = -1e10;
    for(int i = 0; i < n; i++) {
        side.s = poly[i];
        side.e = poly[(i + 1) % n];
        if(OnSeg(p, side))return 0;
        if(sgn(side.s.y - side.e.y) == 0)
            continue;
        if(OnSeg(side.s, ray)) {
            if(sgn(side.s.y - side.e.y) > 0)cnt++;
        } else if(OnSeg(side.e, ray)) {
            if(sgn(side.e.y - side.s.y) > 0)cnt++;
        } else if(inter(ray, side))
            cnt++;
    }
    if(cnt % 2 == 1)return 1;
    else return -1;
}

int n[2];
Point P[2][MX], W[MX], R[MX];

double cross(Point a, Point b, Point c) {
    return ((b.x - a.x) * (c.y - a.y) - (c.x - a.x) * (b.y - a.y));
}
int convex(int n, Point P[], Point R[]) {
    int m = 0, k;
    sort(P, P + n);
    for(int i = 0; i < n; i++) {
        while(m > 1 && cross(R[m - 1], P[i], R[m - 2]) <= 0) m--;
        R[m++] = P[i];
    }

    k = m;
    for(int i = n - 2; i >= 0; i--) {
        while(m > k && cross(R[m - 1], P[i], R[m - 2]) <= 0) m--;
        R[m++] = P[i];
    }
    if(n > 1) m--;
    return m;
}
double CalcArea(Point p[], int n) {
    double res = 0;
    for(int i = 0; i < n; i++)
        res += (p[i] ^ p[(i + 1) % n]) / 2;
    return fabs(res);
}
double solve() {
    int sz = 0;
    for(int t = 0; t <= 1; t++) {
        for(int i = 0; i < n[t]; i++) {
            if(inPoly(P[t][i], P[t ^ 1], n[t ^ 1]) == 1) {
                W[sz++] = P[t][i];
                // fuck(P[t][i].x); fuck(P[t][i].y); puts("");
            }
        }
    }
    for(int i = 0; i < n[0]; i++) {
        Line l1(P[0][i], P[0][(i + 1) % n[0]]);
        for(int j = 0; j < n[1]; j++) {
            Line l2(P[1][j], P[1][(j + 1) % n[1]]);
            if(inter(l1, l2)) {
                pair<int, Point> ret = l1 & l2;
                if(ret.first == 2) W[sz++] = ret.second;
            }
        }
    }
    sz = convex(sz, W, R);
    return CalcArea(R, sz);
}
int main() {
    double x1,y1,x2,y2,x3,y3,x4,y4 ;
    while(~scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2)){
        scanf("%lf%lf%lf%lf",&x3,&y3,&x4,&y4);
        n[0]=3,n[1]=4;
        P[0][0].x=x1;P[0][0].y=y1;
        P[0][1].x=x1;P[0][1].y=y2;
        P[0][2].x=x2;P[0][2].y=y1;
        P[1][0].x=x3;P[1][0].y=y3;
        P[1][1].x=x3;P[1][1].y=y4;
        P[1][2].x=x4;P[1][2].y=y4;
        P[1][3].x=x4;P[1][3].y=y3;
        printf("%.6f\n",solve());
    }
    return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值