《算法竞赛-训练指南》第二章-2.28_LA 3485(simpson)

做这个竞赛题目,就是相当于高中的数学难的题目,你做出来了,万人敬仰,你稍微错了一点,没有做对,那么不好意思,不管你思路对还是很对,你都不是那个会做的人。题目如此,事情也是如此,错过了再想挽回可能就后悔莫及了。

这道题目的主体思想当然是求解,如果你数学的求解能力非常的强,那这个题根本就不是个事,但是你不行的话,那不好意思,你做不出来。

这里用到的求解微积分的面积的时候常用的方法simpson法。我也没去看具体的证明,反正意思就是,把[a, b]一段区间无限分割成dx,然后在dx中近似求解面积,当然这里就要注意,咱们记公式的时候当然是要记住最简便的,现在咱们就讨论f(x)是一条平行于x轴的直线,那么面积(积分)显然就是dx * (y1 + 4y2 + y3)/ 6咯。由此易得三点simpson公式。

而自适应simpson就比较难懂了,说什么设定一个精度,算法就可以递归下去划分区间,容易近似的少划分,不容易近似的多划分,不理解。而且当且仅当s(a,c) + s(c,b) - s(a,b) < 15 * eps的时候就返回结果?不懂。

贴出代码,当以后的模版用吧:

#include <stdio.h>
#include <string.h>
#include <math.h>
#include <iostream>
#include <string>

using namespace std;

int D, H, B, L;

double a;

double F(double x)
{
	return sqrt(1 + 4 * a * a * x * x);
}

double simpson(double a, double b)
{
	double c = a + (b - a) / 2;
	return (F(a) + 4 * F(c) + F(b)) * (b - a) / 6;
}

double asr(double a, double b, double eps, double A)
{
	double c = a + (b - a) / 2;
	double L = simpson(a, c);
	double R = simpson(c, b);
	if (fabs(L + R - A) <= 15 * eps)
	{
		return L + R + (L + R - A) / 15.0;
	}
	return asr(a, c, eps / 2, L) + asr(c, b, eps / 2, R);
}

double asr(double a, double b, double eps)
{
	return asr(a, b, eps, simpson(a, b));
}

double check(double w, double h)
{
	a = 4.0 * h / (w * w);
	return asr(0, w / 2, 1e-5) * 2;
}

int main()
{
	int T;
	scanf("%d", &T);
	for (int Case = 1; Case <= T; Case++)
	{
		scanf("%d%d%d%d", &D, &H, &B, &L);
		int n = (int)ceil((double)B / D);
//		int n = (B + D - 1) / D;
		double s = (double)L / n;
		double w = (double)B / n;
		double L = 0;
		double R = (double)H;
		while (R - L > 1e-5)
		{
			double mid = L + (R - L) / 2;
			if (check(w,mid) < s)
			{
				L = mid;
			}
			else
			{
				R = mid;
			}
		}
		if (Case > 1)
		{
			printf("\n");
		}
		printf("Case %d:\n%.2lf\n", Case, (double)H - L);
		
	}
//	system("pause");
	return 0;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值