您的位置:首页 > 其它

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

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

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

这里用到的求解微积分的面积的时候常用的方法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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: