[CQOI2005]三角形面積並
阿新 • • 發佈:2018-12-27
[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; }