[hdu4498]离散化,simpson求积分

题意:,求这个函数在[0,100]上的图像的长度。

思路:采用离散化的思想,求出所有交点 ,把交点排序,把[0,100]分成若干个小区间,这样原函数在每个小区间上的图像属于某一个二次函数或者是一条直线。如何确定属于哪个呢?比如对于某个区间,令m为这个小区间的中点,求出所有的函数在m点的函数值的最小值,对应的那个函数就是答案。如果最小值>=100则说明是直线。那么问题就变成了求二次函数曲线在区间[L,R]上的长度。这个可以转化为积分来算,令f(x)为原函数的倒数,则答案就是sqrt(1+f(x)*f(x))在[L,R]上的积分了。求积分可以用自适应辛普森法。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <queue>

#include <cmath>

#include <algorithm>

using namespace std;

const int maxn = 123;

#define _x2(a) (a) * (a)

namespace Integral {

    double (*func)(double);

    double simpson(double a, double b) {

        double c = a + (b - a) / 2;

        return (func(a) + func(c) * 4 + func(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), R = simpson(c, b);

        if (fabs(L + R - A) < 15 * eps) return L + R + (L + R - A) / 15;

        return asr(a, c, eps / 2, L) + asr(c, b, eps / 2, R);

    }

    double getans(double a, double b, double eps, double (*f)(double)) {

        func = f;

        return asr(a, b, eps, simpson(a, b));

    }

};

int k[maxn], a[maxn], b[maxn];

int A[maxn], B[maxn], C[maxn];

int ga, gb, gc, cnt;

double pos[12345];

double F(double x) {

    return ga * x * x + gb * x + gc;

}

double f(double x) {

    return sqrt(1.0 + _x2(2.0 * ga * x + gb));

}

void add(double x) {

    if (x > 0 && x < 100) pos[cnt ++] = x;

}

int main() {

#ifndef ONLINE_JUDGE

    freopen("in.txt""r", stdin);

#endif // ONLINE_JUDGE

    int T, n;

    cin >> T;

    while (T --) {

        cnt = 0;

        pos[cnt ++] = 0;

        pos[cnt ++] = 100;

        cin >> n;

        for (int i = 0; i < n; i ++) {

            cin >> k[i] >> a[i] >> b[i];

            A[i] = k[i];

            B[i] = -2 * k[i] * a[i];

            C[i] = k[i] * a[i] * a[i] + b[i];

            if (b[i] < 100) {

                double buf = sqrt((100.0 - b[i]) / k[i]);

                add(a[i] + buf);

                add(a[i] - buf);

            }

        }

        for (int i = 0; i < n; i ++) {

            for (int j = i + 1; j < n; j ++) {

                ga = A[i] - A[j];

                gb = B[i] - B[j];

                gc = C[i] - C[j];

                if (ga == 0) {

                    if (gb != 0) add(-1.0 * gc / gb);

                    continue;

                }

                int d = gb * gb - 4 * ga * gc;

                if (d >= 0) {

                    add((-gb - sqrt(1.0 * d)) / 2.0 / ga);

                    if (d) add((-gb + sqrt(1.0 * d)) / 2.0 / ga);

                }

            }

        }

        sort(pos, pos + cnt);

        double ans = 0;

        for (int i = 1; i < cnt; i ++) {

            double L = pos[i - 1], R = pos[i];

            if (R - L < 1e-10) continue;

            double M = (L + R) / 2, minval = 100;

            int target = -1;

            for (int i = 0; i < n; i ++) {

                ga = A[i];

                gb = B[i];

                gc = C[i];

                if (F(M) < minval) {

                    minval = F(M);

                    target = i;

                }

            }

            if (~target) {

                ga = A[target];

                gb = B[target];

                gc = C[target];

                ans += Integral::getans(L, R, 1e-8, f);

            }

            else ans += R - L;

        }

        printf("%.2f\n", ans);

    }

    return 0;

}

时间: 2024-08-10 19:10:24

[hdu4498]离散化,simpson求积分的相关文章

bzoj1502 simpson求面积

题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1502 题解: simpson积分求面积,s = (f(a)+f(b)+4*f(c))/6*Δx ,c=(a+b)/2. 题中的树投影下来是一些圆和相邻圆的公切线组成的一个封闭图形,并且上下对称,所以可以只求上半部分. simpson求面积时,若f(x)代价很大,要尽量减少其的重复调用.其次尽量优化f(x)函数的计算. 写完后还要自己出极限随机数据,将eps调到能接受的最大值. 1 #incl

定积分(任意函数求积分)

1 #define eps 1e-8 2 3 double fun(double x) { 4 /*函数部分*/ 5 } 6 7 double Definite_Integral(double a, double b) { 8 double p = eps + 1.0; 9 double t, h = b - a, t1 = (fun(a) + fun(b)) * h / 2; 10 while(p >= eps) { 11 double s = 0; 12 for(double k = a +

C语言求积分

编一个程序,求定积分. 1 #include<stdio.h> 2 int main() 3 { 4 float x,n=100000,integral=0,i; 5 for(i=0;i<100000;) 6 { 7 i++; 8 x=n*n; 9 integral+=i/x; 10 } 11 printf("%0.5f\n",integral); 12 return 0; 13 } C语言求积分

复合梯形公式与复合辛普森公式求积分

一 实验目的 1. 掌握复合梯形公式与复合辛普森公式的基本思想.2. 编程实现用复合梯形公式与复合辛普森公式求积分.3. 熟悉matlab软件的使用. 二 实验内容1.用复合梯形公式计算积分 I=4/(1+x2)dx ,求它0到1的积分.精确度为10-5.(0.00001),精确到 ●1 计算公式 h=(b-a)/n h=h/2[(f(x0)+f(x1))+(f(x1)+f(x2))+(f(x2)+f(x3)+...+(f(xn-1)+f(xn)] l1 算法分析 En=h2/12[f'(b)-

ZOJ 3898 Stean 矩形法求积分

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5601 题意:求一个绕y轴旋转的旋转体体积.R = 2+cos(z). 思路:旋转体体积可以直接用积分求出来,旋转体表面积公式对于此题积分比较难积,所以用矩形法来求积分. 1 #include <bits/stdc++.h> 2 using namespace std; 3 int T; 4 double z1, z2, V, area; 5 const doubl

[ An Ac a Day ^_^ ] hdu 5925 Coconuts 离散化+BFS求连通块

东北赛根本就没看懂的的题目…… 也用到了离散化 1e9的x y范围 200个坏点 很典型的离散化数据范围 还是不太为什么离散化的遍历下标都要从1开始…… 所以说只做这道题对离散化的理解还不是很深刻…… 因为可能换一道题又不会了 还是要多做啊 1 #include<bits/stdc++.h> 2 #define cl(a,b) memset(a,b,sizeof(a)) 3 #define debug(x) cerr<<#x<<"=="<<

高斯-勒让德公式 求积分

1 #include <iostream> 2 #include <cmath> 3 using namespace std; 4 //计算f(x)=1/x 在[1,3]上的积分 5 6 double f(double x){ 7 return 1.0/(x+2); 8 } 9 10 double f1(double x){ 11 return 1.0/(x+5); 12 } 13 double f2(double x){ 14 return 1.0/(x+7); 15 } 16

[再寄小读者之数学篇](2014-06-20 求积分)

设 $n\in\bbN^+$, 计算积分 $\dps{\int_0^{\pi/2} \cfrac{\sin nx}{\sin x}\rd x}.$ 解答: (1) 由 $$\beex \bea 2\sin x\cdot \cfrac{1}{2}&=\sin x,\\ 2\sin x\cdot \cos 2x&=\sin 3x-\sin x,\\ 2\sin x\cdot \cos 4x&=\sin 5x-\sin 3x,\\ \cdots&=\cdots,\\ 2\sin

Picture POJ - 1177 线段树+离散化+扫描线 求交叉图像周长

参考  https://www.cnblogs.com/null00/archive/2012/04/22/2464876.html #include <stdio.h> #include <algorithm> #define LEN 10000 using namespace std; struct Node { int left; int right; int count;//被覆盖次数 //所包含的区间数量,如三条[1,2],[2,3],[4,5]线段被覆盖,则line=2