【HDU1724】自适应Simpson积分

1.题目链接。题目的意思很简单,就是求阴影部分的面积,图形是一个椭圆。

2.思路:这个做法当然有很多种了,最暴力的就是直接积分了,用一下三角换元也是很简单的就搞定了。其实化简到最后可能涉及到反三角函数的化简,这个就量力而行了呗,有能力继续的,就可以继续(其实没必要,也不是做数学题),搞不明白反三角怎么化简得,直接就写公式上去。第二种方法就是Simpson积分法了,自适应得Simpson积分很简单得就解决了这个问题。第三种,也是我百思不得为什么WA了得一种,就是使用仿射变换,我们知道,可以把椭圆通过坐标系得放缩变成一个圆,然后在圆里面把面积求出来,因为这个坐标变换是按照比例变换得,所以面积也是成比例的,比如:我们做这样的变换:x0=x,y0=(a/b)y,反解出x,y带入就可以的到一个关于x0,y0的方程,这是一个圆,半径就是a.那么我们知道两条直线在这个变换下还是不变的,所以区间还是[l,r],那么在这个圆里面的面积和之前面积的关系就是:s0=(a/b)s.我们只要把s0求出来就行了,s0很简单求了,分成三个部分,左右的三角形,加上中间的扇形,中间的圆心角用余弦定理求出来,面积搞定,再转代回去,就可以得到s了。emmmmm,可是莫名其妙的WA了,也不知怎么回事,在WA了五六发之后,我一怒之下撸了个Simpson A了它。代码如下:

//#include"stdafx.h"
//#include<iostream>
//#include<cmath>
//using namespace std;
//#pragma warning(disable:4996)
//int main()
//{
//	int T;
//	scanf("%d", &T);
//	int a, b, l, r;
//	while (T--)
//	{
//		scanf("%d%d%d%d", &a, &b, &l, &r);
//		if (l == r)
//		{
//			cout << "0.00" << endl;
//			continue;
//
//		}
//		double ly = sqrt(pow(a, 2) - pow(l, 2));
//		double ry = sqrt(pow(a, 2) - pow(r, 2));
//		double dis = sqrt(pow(l - r, 2) + pow(ly - ry, 2));
//		double csita = (2 * pow(a, 2) - pow(dis, 2))*1.0 / (2 * a*a);
//		double sita = acos(csita);
//		double s1 = a * a*sita / 2;
//		double s2 = abs(l)*sqrt(pow(a, 2) - pow(l, 2)) / 2;
//		double s3 = abs(r)*sqrt(pow(a, 2) - pow(r, 2)) / 2;
//		double s = s1 + s2 + s3;
//		s *= 2;
//		s = s * (b*1.0 / a);
//		printf("%.4lf\n", s);
//	}
//}

#include"stdafx.h"
#include<iostream>
using  namespace std;
const double eps = 1e-9;
#pragma warning(disable:4996)
//f函数
double a, b, l, r;
double f(double x)
{
	return sqrt((1 - x * x / (a*a))*(b*b));
}
//Simpson公式
double simpson(double l, double r)
{
	return (f(l) + 4 * f((l + r) / 2) + f(r))*(r - l) / 6;
}
double simpson(double l, double r,double all,double eps)
{
	double mid = (l + r) / 2;
	double L = simpson(l, mid);
	double R = simpson(mid, r);
	if (fabs(L + R - all) <= 15 * eps)
		return L + R + (L + R - all) / 15;
	return simpson(l, mid, L, eps / 2) + simpson(mid, r, R, eps / 2);
}
double simpson(double l, double r, double eps)
{
	return simpson(l, r, simpson(l, r), eps);
}
int main()
{
	int T;
	scanf("%d", &T);
	while (T--)
	{
		scanf("%lf%lf%lf%lf", &a, &b, &l, &r);
		printf("%.3lf\n", 2*simpson(l, r,1e-4));
	}
	return 0;
}



上边是我用仿射变换的代码,等我找到BUG了,再把它放出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值