模板题 3074. 自适应辛普森积分
题意
思路
辛普森积分:(r - l) * (f(l) + f(mid) * 4 + f(r)) / 6.0 指过l,r,(l + r) / 2 三处确定点在抛物线上的积分的面积
自适应辛普森积分:每次找l~r与l~mid+mid~r比较 fabs<eps说明已经精确可用(对二次函数 次数更高就不好说了)过程就是递归
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps = 1e-12;
double l,r;
double dcmp(double x){
if(fabs(x) < eps) return 0;
if(x > 0) return 1;
return -1;
}
double f(double x){
return sin(x) / x;
}
double simpson(double l,double r){//辛普森积分公式
double mid = (l + r) / 2;
return (r - l) * (f(l) + f(mid) * 4 + f(r)) / 6.0;
}
double asr(double l,double r,double S){
double mid = (l + r) / 2;
double left = simpson(l,mid);
double right = simpson(mid,r);
if(dcmp(S - (left + right)) == 0) return left + right;
return asr(l,mid,left) + asr(mid,r,right);
}
int main(){
scanf("%lf%lf",&l,&r);
printf("%.6f\n",asr(l,r,simpson(l,r)));
return 0;
}
3069. 圆的面积并
题意
思路
将f(x)计算为横坐标=x时跨越的圆在纵坐标方向上的长度
代码
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
const double eps = 1e-8;
const int MaxN = 1e3 + 5;
int n;
struct Point{
double x,y;
}q[MaxN];
struct Circle{
Point C;
double r;
}c[MaxN];
int dcmp(double x){
if(fabs(x) < eps) return 0;
if(x > 0) return 1;
return -1;
}
bool cmp(Point A,Point B){
return A.x < B.x;
}
double f(double x){
int cnt = 0;
double ans = 0;
for(int i = 0;i < n; i++){
double R = c[i].r,dis = fabs(x - c[i].C.x);
if(dcmp(R - dis) <= 0) continue;
double h = sqrt(R * R - dis * dis);
double Y1 = c[i].C.y - h;
double Y2 = c[i].C.y + h;
q[++cnt] = {Y1,Y2};
}
if(cnt == 0) return 0;
sort(q + 1,q + 1 + cnt,cmp);
double lst = q[1].x,ed = q[1].y;
for(int i = 2;i <= cnt; i++){
if(q[i].x <= ed) ed = max(ed,q[i].y);
else{
ans += ed - lst;
lst = q[i].x,ed = q[i].y;
}
}
ans += ed - lst;
return ans;
}
double simpson(double l,double r){
double mid = (l + r) / 2;
return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6.0;
}
double asr(double l,double r,double S){
double mid = (l + r) / 2;
double left = simpson(l,mid);
double right = simpson(mid,r);
if(!dcmp(S - left - right)) return left + right;
return asr(l,mid,left) + asr(mid,r,right);
}
int main()
{
scanf("%d",&n);
for(int i = 0;i < n; i++){
scanf("%lf %lf %lf",&c[i].C.x,&c[i].C.y,&c[i].r);
}
double l = -2000,r = 2000;
printf("%.3f\n",asr(l,r,simpson(l,r)));
return 0;
}