[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;
}
posted @ 2018-12-27 08:46  skylee03  阅读(302)  评论(0编辑  收藏  举报