题目链接:​点击打开链接​

题目大意:求出所给椭圆的蓝色阴影部分面积。由于阴影部分是不规则图形,所以,可以考虑用数值分析的办法-辛普森公式或者牛顿-科特斯公式求积分法,为了增加精度,可以用二分法迭代细化。

解题思路:

这是一道 自适应辛普森积分 的入门题,也是我写的第一道辛普森积分。

题目就是求两条线所夹的椭圆的面积。这是个标准的椭圆,其中心在原点。我好像看到了题目连椭圆面积公式都给了,然而并没有任何用,直接上辛普森!

根据椭圆的对称性,我们求x轴上方的面积然后乘以2就是答案。根据椭圆方程 HDU - 1724: Ellipse_HDU,构造函数 HDU - 1724: Ellipse_ACM_02,其中 y>0,然后对此函数进行自适应辛普森积分就可以了。

写完程序过了样例后立马交,TLE,1000ms。结果发现是 Eps 取的太小了,取了1e-10,随着递归下去,Eps不断除以2,导致不断递归划分,做的次数很多就超时了。这题只要求保留3位小数,所以精度没有太大问题,将Eps改为1e-4立马就AC。

AC 代码

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

double a,b;

double f(double x)
{
return b*sqrt(1-(x*x)/(a*a));
}

double simpson(double l, double r)
{
double mid=l+(r-l)/2;
return (f(l)+4*f(mid)+f(r))*(r-l)/6;
}

double integral(double l, double r, double eps)
{
// 这里 mid 不能定义为全局变量,因为最后一条 return 有两个 mid 若是全局,第二个递归的 mid 会有更换
double mid=l+(r-l)/2;
double st=simpson(l,r), sl=simpson(l,mid), sr=simpson(mid,r);
if(fabs(sl+sr-st)<=15*eps) return sl+sr+(sl+sr-st)/15;
// 这里直接 return st; 会 WA
return integral(l,mid,eps/2)+integral(mid,r,eps/2);
}

int main()
{
int n; scanf("%d",&n);
while(n--)
{
double l,r,eps=1e-4;
scanf("%lf%lf%lf%lf",&a,&b,&l,&r);
printf("%.3f\n",2*integral(l,r,eps));
}

return 0;
}