【洛谷】P4207 [NOI2005]月下柠檬树
题解
原来自适应simpson积分是个很简单的东西!
我们尝试分析一下影子,圆的投影还是圆,圆锥的尖投影成一个点,而圆台的棱是圆的公切线,我们把圆心投影出来,发现平面上圆心的距离是两两高度差/tan(alpha)
这是一个轴对称图形,我们只需要求一侧就好了
用simpson积分的公式
\(S = \frac{b - a}{6}(f(a) + 4 * f(\frac{a + b}{2}) + f(b))\)
计算区间就好了,啥,你说肯定不对……
确实肯定不对,然而你可以递归,如何判断这个区间计算的和正确答案相差无几呢,就是左右分别积分出来的值和整个区间的积分相差小于精度的时候就可以认为积分正确了,返回即可,否则左右递归计算积分
代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <ctime>
//#define ivorysi
#define MAXN 505
#define eps 1e-7
#define pb push_back
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
inline db o(db x) {
return x * x;
}
bool dcmp(db a,db b) {
return fabs(a - b) <= eps;
}
struct Point {
db x,y;
Point(){}
Point(db _x,db _y) {
x = _x;y = _y;
}
friend Point operator + (const Point &a,const Point &b) {
return Point(a.x + b.x,a.y + b.y);
}
friend Point operator - (const Point &a,const Point &b) {
return Point(a.x - b.x,a.y - b.y);
}
friend Point operator * (const Point &a,const db &d) {
return Point(a.x * d,a.y * d);
}
friend db operator * (const Point &a,const Point &b) {
return a.x * b.y - a.y * b.x;
}
db norm() {
return sqrt(x * x + y * y);
}
friend db dot(const Point &a,const Point &b) {
return a.x * b.x + a.y * b.y;
}
}P[MAXN];
struct Seg {
Point a,b;
db d;
Seg(){}
Seg(Point _a,Point _b) {
a = _a;b = _b;
d = (b.y - a.y) / (b.x - a.x);
}
friend Point Cross_Point(const Seg &s,const Seg &t) {
db S1 = (s.a - t.a) * (t.b - t.a);
db S2 = (s.b - t.b) * (t.a - t.b);
return s.a + (s.b - s.a) * (S1 / (S1 + S2));
}
}S[MAXN];
db alpha;
db H[MAXN],R[MAXN];
int N;
db F(db x) {
db res = 0;
for(int i = 1 ; i <= N ; ++i) {
if(i != N) {
if(P[i + 1].x - P[i].x > fabs(R[i] - R[i + 1])) {
if(S[i].a.x + eps <= x && x <= S[i].b.x - eps) {
res = max(res,S[i].a.y + (x - S[i].a.x) * S[i].d);
}
}
}
if(x >= P[i].x - R[i] && x <= P[i].x + R[i]) {
res = max(res,sqrt(o(R[i]) - o(P[i].x - x)));
}
}
return res;
}
db calc(db L,db R) {
db mid = (L + R) / 2;
return (R - L) * (F(L) + F(R) + 4 * F((L + R) / 2)) / 6;
}
db Simpson(db L,db R) {
db mid = (L + R) / 2;
db Slr = calc(L,R),Sl = calc(L,mid),Sr = calc(mid,R);
if(dcmp(Slr,Sl + Sr)) return Sl + Sr;
else return Simpson(L,mid) + Simpson(mid,R);
}
void Init() {
scanf("%d%lf",&N,&alpha);
++N;
for(int i = N ; i >= 1; --i) scanf("%lf",&H[i]);
R[1] = 0;
for(int i = N ; i >= 2; --i) scanf("%lf",&R[i]);
for(int i = 1 ; i <= N ; ++i) H[i] /= tan(alpha);
P[1] = Point(0,0);
for(int i = 2 ; i <= N ; ++i) {
P[i] = Point(P[i - 1].x + H[i - 1],0);
}
}
void Solve() {
db r = 0,l = 0;
for(int i = 1 ; i <= N ; ++i) {
l = min(P[i].x - R[i],l);
r = max(r,P[i].x + R[i]);
}
for(int i = 1 ; i < N ; ++i) {
if(P[i + 1].x - P[i].x > fabs(R[i] - R[i + 1])) {
db C = (R[i] - R[i + 1]) / (P[i + 1].x - P[i].x);
db s1 = P[i].x + R[i] * C,s2 = P[i + 1].x + R[i + 1] * C;
db h1 = sqrt(o(R[i]) - o(P[i].x - s1)),h2 = sqrt(o(R[i + 1]) - o(P[i + 1].x - s2));
S[i] = Seg(Point(s1,h1),Point(s2,h2));
}
}
printf("%.2lf\n",Simpson(l,r) * 2);
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
}
【洛谷】P4207 [NOI2005]月下柠檬树的更多相关文章
- 洛谷P4207 [NOI2005]月下柠檬树(计算几何+自适应Simpson法)
题面 传送门 题解 我还好奇自适应辛普森法干嘛用的呢--突然想起来积分的一个用处就是求曲边图形的面积-- 我们先来考虑一下这些投影是什么形状 一个圆的投影还是它自己 一个圆锥的投影是一个圆加上一个点, ...
- 5.21 省选模拟赛 luogu P4207 [NOI2005]月下柠檬树 解析几何 自适应辛普森积分法
LINK:月下柠檬树 之前感觉这道题很鬼畜 实际上 也就想到辛普森积分后就很好做了. 辛普森积分法的式子不再赘述 网上多的是.值得一提的是 这道题利用辛普森积分法的话就是一个解析几何的问题 而并非计算 ...
- BZOJ 1502: [NOI2005]月下柠檬树 [辛普森积分 解析几何 圆]
1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1070 Solved: 596[Submit][Status] ...
- [NOI2005]月下柠檬树[计算几何(simpson)]
1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 1169 Solved: 626[Submit][Status] ...
- 【BZOJ1502】[NOI2005]月下柠檬树 Simpson积分
[BZOJ1502][NOI2005]月下柠檬树 Description 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树 ...
- [NOI2005]月下柠檬树
题意 F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入门OJ ModifyUser autoint Logout 捐赠本站 Probl ...
- BZOJ1502:[NOI2005]月下柠檬树——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1502 https://www.luogu.org/problemnew/show/P4207 李哲 ...
- 1502: [NOI2005]月下柠檬树 - BZOJ
Description Input 文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度).第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的 ...
- [NOI2005]月下柠檬树(计算几何+积分)
题目描述 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔 地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树旁,独自思 索着人生的哲理. 李哲是一个喜爱思考的孩子,当他看 ...
随机推荐
- SQL统计每科前三名的学生的语句
偶然在论坛看到一个网友的帖子,关于他遇到一个面试题的,网站写了很多,我看了一下,结果应该是没问题的,但是为何面试官还是不满意,我想面试官可能并不是想考你真能把这道题做出来,而是看你如何简洁的通过一个s ...
- day10 浅谈面向对象编程
面向对象编程:第一步找名词,名词是问题域中的. 第二步概括名词设计成类.某些名词可以浓缩包含到其它名词中,成为其属性. 第三步找动词,动词也是问题域中的. 第四步概括动词设计成方法.动作的产生往往 ...
- 如何在Mongodb中实现数据超时自动删除功能?
在工作过程中,我们难免会遇到这样的问题,我们想保存一些数据,但是我们对这些数据的要求并不高,有时候往往只是想要某个时间范围内的数据,比如我们如果永远只关心从当前时间往前推半年内的数据特性,那么我们就不 ...
- Linux基础命令【记录】
后台运行详情:https://www.cnblogs.com/little-ant/p/3952424.html 查看端口.查找等命令 根据关键字查找文件信息: cat <文件名> | g ...
- git爬坑不完全指北(二):failed to push some refs to ‘XXX’的解决方案
报错分析 从字面理解,这个报错的意思就是说远程仓库里有一个改动是本地仓库里没有的,所以在push前要先把远程仓库上的改动pull或者fetch到本地仓库.然后再执行push的操作,把本地 ...
- Chrome浏览器F12讲解
Chrome浏览器相对于其他的浏览器而言,DevTools(开发者工具)非常强大.这节课将为大家介绍怎么利用Chrome浏览器的开发者工具进行HTTP请求分析 Chrome浏览器讲解 Chrome 开 ...
- Codeforces 877 C. Slava and tanks
http://codeforces.com/problemset/problem/877/C C. Slava and tanks time limit per test 2 seconds me ...
- Linux系统中连接使用NAS
在使用NAS时,需要先确定NAS上的NFS服务和SMB的服务都开启了: 然后需要用NAS上的用户去登录,这里用的是admin: # smbclient -L 192.168.1.40 -U admin ...
- python 分布式进程体验
抽了点时间体验了一把python 分布式进程,有点像分布式计算的意思,不过我现在还没有这个需求,先把简单体验的脚本发出来,供路过的各位高手指教 注:需要先下载multiprocessing 的pyth ...
- Linux 下子进程与父进程的关系
我们知道,Linux下父进程可以使用fork 函数创建子进程,但是当父进程先退出后,子进程会不会也退出呢? 通过下面这个小实验,我们能够很好的看出来: /******** basic.c ****** ...