zoukankan      html  css  js  c++  java
  • [CQOI2005]三角形面积并

    [CQOI2005]三角形面积并

    题目大意:

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

    思路:

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

    源代码:

    #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
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    oracle RAC 更换IP
    12C oracle 12.1.0.2版本打补丁
    node name配置错误,导致grid日志在报警
    input_subsys 输入子系统框架分析
    www.bing.com
    getopt函数使用说明
    FreeType 矢量字体 测试移植(1)
    字符的编码方式
    在开发板上显示字符和中文
    块设备驱动程序的框架
  • 原文地址:https://www.cnblogs.com/skylee03/p/10182995.html
Copyright © 2011-2022 走看看