【bzoj1502】[NOI2005]月下柠檬树 自适应Simpson积分
题目描述

输入
输出
输出1个实数,表示树影的面积。四舍五入保留两位小数。
样例输入
2 0.7853981633
10.0 10.00 10.00
4.00 5.00
样例输出
171.97
题解
自适应Simpson积分
根据数学知识:在平行光投影下,圆的半径保持不变,位置为 高度/tanα ;圆台/圆锥的侧面投影为两圆/一圆一点的外公切线。
那么先将圆的位置求出,然后依次求相邻两圆公切线并将线段记录,此时注意内切/内含的两个圆是没有外公切线的。这里求公切线使用了射影定理。
如下图:

其中黑色的是投影后的圆,红色的是公切线段。
那么我们要求的就是最外层轮廓所围成的图形的面积。由于对称性因此只需要求出上半部分然后乘2。
注意到上半部分的外层轮廓形成了连续的一段函数,因此考虑使用自适应Simpson积分来求面积。
Simpson积分:对于三次及以下多项式函数,有 $\int_l^rf(x)dx=(r-l)·\frac {f(l)+f(r)+4f(\frac{l+r}2)}6$ 。
自适应Simpson积分:对于任意连续函数 $f(x)$ 求 $\int_l^rf(x)dx$,先将其当作三次函数使用Simpson积分求出 $[l,r]$ 、$[l,mid]$ 和 $[mid+r]$ 的面积,如果左半部分和右半部分面积之和与总面积之差满足精度要求则返回,否则递归左右并求和作为总面积。
本质上相当于插一个三次函数,如果差得比较多则递归左右。
回过头来看本题,问题变为:给出 $x$ ,求 $f(x)$ 。显然可以在每个圆和每条线段上(如果存在)求出 $x$ 的函数值,取最大值即为 $f(x)$ 。
注意精度要设得小一些,因为求和的部分使误差增大。
时间复杂度 $O(跑得过)$ 。
#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 510
#define eps 1e-5
using namespace std;
struct circle
{
double x , r;
}c[N];
struct line
{
double x1 , y1 , x2 , y2;
}l[N];
double h[N];
int n , m;
inline double squ(double x)
{
return x * x;
}
inline double f(double p)
{
int i;
double ans = 0;
for(i = 1 ; i <= n ; i ++ )
if(p >= c[i].x - c[i].r && p <= c[i].x + c[i].r)
ans = max(ans , sqrt(squ(c[i].r) - squ(p - c[i].x)));
for(i = 1 ; i <= m ; i ++ )
if(p >= l[i].x1 && p <= l[i].x2)
ans = max(ans , l[i].y1 + (p - l[i].x1) * (l[i].y2 - l[i].y1) / (l[i].x2 - l[i].x1));
return ans;
}
inline double calc(double l , double r)
{
return (r - l) * (f(l) + f(r) + f((l + r) / 2) * 4) / 6;
}
double simpson(double l , double r , double s)
{
double mid = (l + r) / 2 , x = calc(l , mid) , y = calc(mid , r);
if(fabs(x + y - s) <= eps) return s;
return simpson(l , mid , x) + simpson(mid , r , y);
}
int main()
{
int i;
double alpha , t , L = 1e9 , R = -1e9;
scanf("%d%lf" , &n , &alpha) , n ++ ;
for(i = 1 ; i <= n ; i ++ ) scanf("%lf" , &h[i]) , h[i] += h[i - 1] , c[i].x = h[i] / tan(alpha);
for(i = 1 ; i < n ; i ++ ) scanf("%lf" , &c[i].r);
for(i = 1 ; i < n ; i ++ )
{
if(c[i + 1].x - c[i].x > fabs(c[i + 1].r - c[i].r))
{
m ++ ;
t = c[i].r * (c[i].r - c[i + 1].r) / (c[i + 1].x - c[i].x) , l[m].x1 = c[i].x + t , l[m].y1 = sqrt(squ(c[i].r) - squ(t));
t = c[i + 1].r * (c[i].r - c[i + 1].r) / (c[i + 1].x - c[i].x) , l[m].x2 = c[i + 1].x + t , l[m].y2 = sqrt(squ(c[i + 1].r) - squ(t));
}
}
for(i = 1 ; i <= n + 1 ; i ++ ) L = min(L , c[i].x - c[i].r) , R = max(R , c[i].x + c[i].r);
printf("%.2lf\n" , 2 * simpson(L , R , calc(L , R)));
return 0;
}
【bzoj1502】[NOI2005]月下柠檬树 自适应Simpson积分的更多相关文章
- [BZOJ 1502] [NOI2005] 月下柠檬树 【Simpson积分】
题目链接: BZOJ - 1502 题目分析 这是我做的第一道 Simpson 积分的题目.Simpson 积分是一种用 (fl + 4*fmid + fr) / 6 * (r - l) 来拟合 fl ...
- [BZOJ1502]月下柠檬树(自适应辛普森积分)
1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1387 Solved: 739[Submit][Status] ...
- [日常摸鱼]bzoj1502[NOI2005]月下柠檬树-简单几何+Simpson法
关于自适应Simpson法的介绍可以去看我的另一篇blog http://www.lydsy.com/JudgeOnline/problem.php?id=1502 题意:空间里圆心在同一直线上且底面 ...
- BZOJ 1502 月下柠檬树(simpson积分)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1502 题意:给出如下一棵分层的树,给出每层的高度和每个面的半径.光线是平行的,与地面夹角 ...
- BZOJ1502: [NOI2005]月下柠檬树
Simpson法相当好用啊!神奇的骗分算法! /************************************************************** Problem: 1502 ...
- bzoj 1502 月下柠檬树【Simpson积分】
投影到地面之后,会发现圆形在平行光下面积和形状是不会变的,也就是所要求的图形是若干个圆和把相邻两个圆连起来的公切线所组成的. 公切线和圆间距瞎求一下就行,注意要去掉被完全覆盖的圆 然后simpson即 ...
- 【BZOJ1502】[NOI2005]月下柠檬树 Simpson积分
[BZOJ1502][NOI2005]月下柠檬树 Description 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树 ...
- 【BZOJ-1502】月下柠檬树 计算几何 + 自适应Simpson积分
1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1017 Solved: 562[Submit][Status] ...
- BZOJ 1502: [NOI2005]月下柠檬树 [辛普森积分 解析几何 圆]
1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1070 Solved: 596[Submit][Status] ...
随机推荐
- 20155325 信息安全技术 实验二 Windows口令破解
内容一览 实验结果 遇到的问题 思考题 详细步骤与解析(为了使存做笔记资料而做) 实验结果 字典破解 暴力破解 -不同密码强度的破解时间比较 用户名 密码 破解方式 破解时间 TEST (年月日) 字 ...
- 【LG3723】[AHOI2017/HNOI2017]礼物
[LG3723][AHOI2017/HNOI2017]礼物 题面 洛谷 题解 首先我们将\(c\)看作一个可以为负的整数,那么我们就可以省去讨论在哪个手环加\(c\)的繁琐步骤了 设我们当前已经选好了 ...
- PHP 行为测试工具 Codeception (介绍)
原文地址:https://phphub.org/topics/25 Codeception 简介 Codeception 简单来说, 分为以下几种测试 Acceptance Tests 验收测试 Fu ...
- python进程-进阶
进程同步(multiprocessing.Lock(锁机制).multiprocessing.Semaphore(信号量机制).multiprocessing.Event(事件机制)) 在计算机中,有 ...
- 安装Vue.js的方法有三种
1 使用独立的版本 在Vue.js官网上直接下载,在script标签里引用. 2 使用CND方法(不推荐) 3 NMP 方法 在用Vue.js构建大型应用的时候推荐使用NMP安装方法,NMP能很好的和 ...
- Jmeter如何做接口测试
最近在学习Jmeter,记录下来,与大家分享. 1. 打开Jmeter,我用的是5.0版本,打开后如下图所示: 2. 右键测试计划,添加 - 线程(用户) - 线程组,如下如图所示: 3. 右键线程组 ...
- Python中abs()和math.fabs()区别
描述:Python中fabs(x)方法返回x的绝对值.虽然类似于abs()函数,但是两个函数之间存在以下差异: abs()是一个内置函数,而fabs()在math模块中定义的. fabs()函数只适用 ...
- centos7挂载Windows共享文件夹(学习笔记)
centos7挂载windows共享文件夹 练习环境:centos7是安装在台式机的虚拟机,Windows共享文件夹是公司服务器的共享文件夹(已设置好的共享) 步骤 1. 设置挂载点:mkdir /m ...
- 【RL系列】从蒙特卡罗方法步入真正的强化学习
蒙特卡罗方法给我的感觉是和Reinforcement Learning: An Introduction的第二章中Bandit问题的解法比较相似,两者皆是通过大量的实验然后估计每个状态动作的平均收益. ...
- We are writing to let you know we have removed your selling privileges
Hello, We are writing to let you know we have removed your selling privileges, canceled your listin ...