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;
}
时间: 2024-11-14 14:33:50

BZOJ 2178 圆的面积并 Simpson自适应公式的相关文章

BZOJ 2178 圆的面积并 Simpson积分

题意:链接 方法: Simpson积分 解析: 这题是有正解的=-= 不过Simpson积分可过. 首先 ∫rlf(x)=(r?l)(f(l)+f(r)+4f(mid))6 然后就强行递归搞就行了. 至于f(i)的值,在本题就是x=i这条直线与所有可以相交的圆的截线长的和. 这个的话用勾股定理求即可. 然后有一个方法 Simpson积分自适应法=-= 我们只需要强行套用公式,然后检验左半边的如上函数值加上右半边的如上函数值与我们强行套用公式得出来的值是否在精度范围允许内,如果在的话直接retur

BZOJ 2178 圆的面积并 ——Simpson积分

[题目分析] 史上最良心样例,史上最难调样例. Simpson积分硬上. 听说用long double 精度1e-10才能过. 但是double+1e-6居然过了. [代码] #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <map> #include <set> #include <queue> #incl

BZOJ 2178: 圆的面积并 [辛普森积分 区间并]

2178: 圆的面积并 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1740  Solved: 450[Submit][Status][Discuss] Description 给出N个圆,求其面积并 Input 先给一个数字N ,N< = 1000 接下来是N行是圆的圆心,半径,其绝对值均为小于1000的整数 Output 面积并,保留三位小数 太可怕了!!!!!! 直接上辛普森积分 函数值就是x=..线上的区间并 区间并直接排序扫描就可以了

BZOJ 1502 NOI2005 月下柠檬树 Simpson自适应公式

题目大意:给定一棵由圆台和圆锥构成的柠檬树,月光以α的夹角平行射向地面,求阴影部分面积 补充题目大意:看到这题我产生了心理阴影,求阴影部分面积 题目不好分析,但其实就是求一堆圆和一堆梯形的面积交 样例如图(画的有点烂),将顶点看做半径为0的圆,则图中圆的半径即为给定圆的半径,圆心距为h/tan(α),直线为两圆公切线 这题我们采用辛普森自适应公式 首先辛普森公式见度受百科 http://baike.baidu.com/view/2710883.htm?fr=aladdin 比较遗憾的是 辛普森公

bzoj 2178 圆的面积并【simpson积分】

直接套simpson,f可以直接把圆排序后扫一遍所有圆,这样维护一个区间就可以避免空段. 然而一定要去掉被其他圆完全覆盖的圆,否则会TLE #include<iostream> #include<cstdio> #include<algorithm> #include<cmath> using namespace std; const double eps=1e-13; const int N=1005; int n,m; double mn=1e13,mx

【BZOJ】2178: 圆的面积并

http://www.lydsy.com/JudgeOnline/problem.php?id=2178 题意:给出n<=1000个圆,求这些圆的面积并 #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue> #in

【BZOJ】【2178】圆的面积并

自适应辛普森积分 Orz Hzwer 辛普森真是个强大的东西……很多东西都能积= = 这题的正解看上去很鬼畜,至少我这种不会计算几何的渣渣是写不出来……(对圆的交点求图包,ans=凸包的面积+一堆弓形的面积,另外还有中空的情况……那种凸包怎么求啊喂!) 1 /************************************************************** 2 Problem: 2178 3 User: Tunix 4 Language: C++ 5 Result: A

SPOJ CIRU SPOJ VCIRCLE 圆的面积并问题

SPOJ VCIRCLE SPOJ CIRU 两道题都是给出若干圆 就面积并,数据规模和精度要求不同. 求圆面积并有两种常见的方法,一种是Simpson积分,另一种是几何法. 在这里给出几何方法. PS.以下算法基于正方向为逆时针 考虑上图中的蓝色圆,绿色的圆和蓝色的圆交于 A,B 2个交点 ,我们在逆时针系下考虑,那么 可以知道 对于蓝色的圆,它对应的某个 角度区间被覆盖了 假设 区间为 [A, B], 并且角度是按照 圆心到交点的 向量的 极角来定义 (为了方便,我一般都把角度转化到 [0,

POJ 2546 &amp; ZOJ 1597 Circular Area 两圆的面积交

Circular Area Time Limit: 2 Seconds      Memory Limit: 65536 KB Your task is to write a program, which, given two circles, calculates the area of their intersection with the accuracy of three digits after decimal point. Input In the single line of in