自适应Simpson积分
一般用于在坐标系上求面积。
公式是\( S=\frac{f(l)+4*f(mid)+f(r)}{6} \),其中f为对应x的y值。也就是用二次函数拟合。
至于为什么是自适应:因为使用二次函数拟合,所以对于一段x区间[a,b],考虑对[a,b]求S,再求[a,(a+b)/2]和[(a+b)/2,b]的S和。然后看这两部分的差是否在eps内,是的话则返回答案,否则递归求解[a,(a+b)/2]和[(a+b)/2,b]。这样一来,对于比较波折的段,会递归到较为精确的[a,b],对于较平滑的段则会去少数点。
例题:
hdu 1071
题意:求椭圆面积
直接板子,注意结果*2
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;
const double eps=1e-9;
int T;
double a,b,l,r;
int cmp(double x)
{
if(x<=eps&&x>=-eps)
return 0;
return x>0?1:-1;
}
double f(double x)
{
return b*sqrt(1.0-x*x/(a*a));
}
double sps(double l,double r,double now,double fl,double fr,double fm)
{
double mid=(l+r)/2,ffl=f((l+mid)/2),ffr=f((mid+r)/2),p=(fl+fm+ffl*4)*(mid-l)/6,q=(fm+fr+ffr*4)*(r-mid)/6;
if(cmp(now-p-q)==0)
return now;
else
return sps(l,mid,p,fl,fm,ffl)+sps(mid,r,q,fm,fr,ffr);
}
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%lf%lf%lf%lf",&a,&b,&l,&r);
double fl=f(l),fr=f(r),fm=f((l+r)/2);
printf("%.3lf\n",2*sps(l,r,(fl+4*fm+fr)*(r-l)/6,fl,fr,fm));
}
return 0;
}
bzoj 2178 https://www.cnblogs.com/lokiii/p/8452281.html
bzoj 1502 https://www.cnblogs.com/lokiii/p/8452291.html