首页 > 代码库 > BZOJ 2178 圆的面积并 Simpson自适应公式

BZOJ 2178 圆的面积并 Simpson自适应公式

题目大意:给定n个圆,求面积并

直接暴力套用Simpson自适应公式就行了

对于每一个x值,求出F(x)的方法是求出所有圆在直线x=x(重了233)上的截取区间

然后求区间并 返回区间长度即是F值

这样正常写就过样例了 然后 WA了。。。

尼玛我样例都过了你跟我说WA?

下面是注意事项:

1.此题卡精度 EPS要设为1e-13 设为1e-12会WA

2.标程精度不够 不能用long double 否则会WA

3.这样会TLE 解决方法是预先将内含与其他圆的圆删掉 然后就能过了

这明显是卡数据啊- - 没办法了- -

此外顺便学习了一下类继承的东西- -

#include <map>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define M 1010
#define EPS 1e-13
using namespace std;
typedef double ld;
struct Point{
	ld x,y;
	Point() {}
	Point(ld _,ld __):
		x(_),y(__) {}
};
struct Circle:Point{
	ld r;
	void Read()
	{
		int x,y,r;
		scanf("%d%d%d",&x,&y,&r);
		this->x=x;
		this->y=y;
		this->r=r;
	}
	bool operator < (const Circle &c) const
	{
		return r < c.r;
	}
}circles[M];
struct Interval{
	ld l,r;
	Interval() {}
	Interval(ld _,ld __):
		l(_),r(__) {}
	bool operator < (const Interval &i) const
	{
		return l<i.l;
	}
};
int n;
ld ans;
ld F(ld x)
{
	static Interval intervals[M];
	static map<ld,ld> a;
	static map<ld,ld>::iterator it;
	if( (it=a.find(x))!=a.end() )
		return it->second;
	int i,tot=0;
	ld& re=a[x];
	memset(intervals,0,sizeof intervals);
	for(i=1;i<=n;i++)
	{
		ld dis=fabs(x-circles[i].x);
		if( dis>=circles[i].r )
			continue;
		ld delta=sqrt(circles[i].r*circles[i].r-dis*dis);
		intervals[++tot]=Interval(circles[i].y-delta,circles[i].y+delta);
	}
	if(!tot) return re=0.0;
	sort(intervals+1,intervals+tot+1);
	ld temp=-1e5;
	for(i=1;i<=tot;i++)
	{
		if(intervals[i].r<=temp)
			continue;
		re+=intervals[i].r-max(intervals[i].l,temp);
		temp=intervals[i].r;
	}
	return re;
}
ld Simpson_Integral(ld l,ld r)
{
	ld mid=(l+r)/2.0;
	return (r-l)*(F(l)+F(r)+4.0*F(mid))/6.0;
}
ld Self_Adjusted_Simpson_Integral(ld l,ld r,ld area)
{
	ld mid=(l+r)/2.0;
	ld l_area=Simpson_Integral(l,mid);
	ld r_area=Simpson_Integral(mid,r);
	if(fabs(l_area+r_area-area)<EPS)
		return l_area+r_area;
	return Self_Adjusted_Simpson_Integral(l,mid,l_area)+Self_Adjusted_Simpson_Integral(mid,r,r_area);
}
ld Distance(const Point &p1,const Point &p2)
{
	return sqrt( (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) );	
}
void Read()
{
	static bool del[M];
	int i,j,tot=0;
	for(i=1;i<=n;i++)
		circles[i].Read();
	for(i=1;i<=n;i++)
		for(j=i+1;j<=n;j++)
			if(circles[j].r-circles[i].r>=Distance(circles[i],circles[j]) )
			{
				del[i]=1;
				break;
			}
	for(i=1;i<=n;i++)
		if(!del[i])
			circles[++tot]=circles[i];
	n=tot;
}
int main()
{
	static Interval intervals[M];
	int i,tot=0;
	cin>>n;
	Read();
	for(i=1;i<=n;i++)
		intervals[++tot]=Interval(circles[i].x-circles[i].r,circles[i].x+circles[i].r);
	sort(intervals+1,intervals+tot+1);
	ld temp=-1e5;
	for(i=1;i<=tot;i++)
	{
		if(intervals[i].r<=temp)
			continue;
		ld l=max(intervals[i].l,temp);	
		ans+=Self_Adjusted_Simpson_Integral(l,intervals[i].r,Simpson_Integral(l,intervals[i].r));
		temp=intervals[i].r;
	}
	cout<<fixed<<setprecision(3)<<ans<<endl;
	return 0;
}


BZOJ 2178 圆的面积并 Simpson自适应公式