[CQOI2005]三角形面积并

[CQOI2005]三角形面积并

题目大意:

\(n(n\le100)\)个三角形的面积并。

思路:

自适应辛普森法,玄学卡精度可过。

源代码:

#include<cmath>
#include<cstdio>
#include<cctype>
#include<vector>
#include<algorithm>
inline int getint() {
    register char ch;
    while(!isdigit(ch=getchar()));
    register int x=ch^'0';
    while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    return x;
}
const int N=101;
const double eps=1e-10;
struct Point {
    double x,y;
};
struct Triangle {
    Point p1,p2,p3;
};
Triangle t[N];
struct Node {
    double p;
    int v,id;
    bool operator < (const Node &rhs) const {
        return p<rhs.p;
    }
};
std::vector<Node> v;
std::vector<int> c;
inline bool cross(const Point &a,const Point &b,const double &x) {
    if(a.x==b.x) return false;
    if(a.x<b.x) {
        return a.x<=x&&x<b.x;
    } else {
        return b.x<x&&x<=a.x;
    }
}
inline double calc(const Point &a,const Point &b,const double &x) {
    return (b.y-a.y)/(b.x-a.x)*(x-a.x)+a.y;
}
inline double F(const double &x) {
    std::vector<std::pair<double,int> > v;
    for(register unsigned j=0;j<c.size();j++) {
        const int &i=c[j];
        double q[3];
        int h=0;
        if(cross(t[i].p1,t[i].p2,x)) {
            q[h++]=calc(t[i].p1,t[i].p2,x);
        }
        if(cross(t[i].p2,t[i].p3,x)) {
            q[h++]=calc(t[i].p2,t[i].p3,x);
        }
        if(cross(t[i].p3,t[i].p1,x)) {
            q[h++]=calc(t[i].p3,t[i].p1,x);
        }
        if(h==2) {
            if(q[0]>q[1]) std::swap(q[0],q[1]);
            v.push_back(std::make_pair(q[0],1));
            v.push_back(std::make_pair(q[1],-1));
        }
    }
    std::sort(v.begin(),v.end());
    double st,ans=0;
    for(register unsigned i=0,tmp=0;i<v.size();i++) {
        if(tmp==0) st=v[i].first;
        tmp+=v[i].second;
        if(tmp==0) {
            ans+=v[i].first-st;
        }
    }
    return ans;
}
inline double simpson(const double &fl,const double &fm,const double &fr,const double &len) {
    return (fl+4*fm+fr)*len/6;
}
inline double asr(const double &a,const double &b,const double &fl,const double &fm,const double &fr,const int &d) {
    const double c=(a+b)/2;
    const double flm=F((a+c)/2),frm=F((c+b)/2);
    const double ls=simpson(fl,flm,fm,c-a),rs=simpson(fm,frm,fr,b-c),s=simpson(fl,fm,fr,b-a);
    if(fabs(ls+rs-s)<eps&&d>13) return ls+rs;
    return asr(a,c,fl,flm,fm,d+1)+asr(c,b,fm,frm,fr,d+1);
}
int main() {
    const int n=getint();
    for(register int i=1;i<=n;i++) {
        scanf("%lf%lf%lf%lf%lf%lf",&t[i].p1.x,&t[i].p1.y,&t[i].p2.x,&t[i].p2.y,&t[i].p3.x,&t[i].p3.y);
        v.push_back((Node){std::min(std::min(t[i].p1.x,t[i].p2.x),t[i].p3.x),1,i});
        v.push_back((Node){std::max(std::max(t[i].p1.x,t[i].p2.x),t[i].p3.x),-1,i});
    }
    std::sort(v.begin(),v.end());
    int tmp=0,beg;
    double ans=0;
    for(register unsigned i=0;i<v.size();i++) {
        if(tmp==0) beg=i;
        tmp+=v[i].v;
        if(tmp==0) {
            for(register unsigned j=beg;j<=i;j++) {
                c.push_back(v[j].id);
            }
            std::sort(c.begin(),c.end());
            c.resize(std::unique(c.begin(),c.end())-c.begin());
            const double &st=v[beg].p,&en=v[i].p;
            ans+=asr(st,en,F(st),F((st+en)/2),F(en),1);
            c.clear();
        }
    }
    printf("%.2f\n",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/skylee03/p/10182995.html