题解

原来自适应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]月下柠檬树的更多相关文章

  1. 洛谷P4207 [NOI2005]月下柠檬树(计算几何+自适应Simpson法)

    题面 传送门 题解 我还好奇自适应辛普森法干嘛用的呢--突然想起来积分的一个用处就是求曲边图形的面积-- 我们先来考虑一下这些投影是什么形状 一个圆的投影还是它自己 一个圆锥的投影是一个圆加上一个点, ...

  2. 5.21 省选模拟赛 luogu P4207 [NOI2005]月下柠檬树 解析几何 自适应辛普森积分法

    LINK:月下柠檬树 之前感觉这道题很鬼畜 实际上 也就想到辛普森积分后就很好做了. 辛普森积分法的式子不再赘述 网上多的是.值得一提的是 这道题利用辛普森积分法的话就是一个解析几何的问题 而并非计算 ...

  3. BZOJ 1502: [NOI2005]月下柠檬树 [辛普森积分 解析几何 圆]

    1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1070  Solved: 596[Submit][Status] ...

  4. [NOI2005]月下柠檬树[计算几何(simpson)]

    1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1169  Solved: 626[Submit][Status] ...

  5. 【BZOJ1502】[NOI2005]月下柠檬树 Simpson积分

    [BZOJ1502][NOI2005]月下柠檬树 Description 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树 ...

  6. [NOI2005]月下柠檬树

    题意 F.A.Qs Home Discuss ProblemSet Status Ranklist Contest 入门OJ ModifyUser  autoint Logout 捐赠本站 Probl ...

  7. BZOJ1502:[NOI2005]月下柠檬树——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=1502 https://www.luogu.org/problemnew/show/P4207 李哲 ...

  8. 1502: [NOI2005]月下柠檬树 - BZOJ

    Description Input 文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度).第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的 ...

  9. [NOI2005]月下柠檬树(计算几何+积分)

    题目描述 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔 地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树旁,独自思 索着人生的哲理. 李哲是一个喜爱思考的孩子,当他看 ...

随机推荐

  1. table 样式美化

    1. 单像素边框CSS表格 这是一个很常用的表格样式. 源代码: <!-- CSS goes in the document HEAD or added to your external sty ...

  2. 安装VisualSVN Server 报错The specified TCP port is occupied

    安装过程中报错,如下图所示. The specified TCP port is occupied by another service.Please stop that service or use ...

  3. 如何在Mongodb中实现数据超时自动删除功能?

    在工作过程中,我们难免会遇到这样的问题,我们想保存一些数据,但是我们对这些数据的要求并不高,有时候往往只是想要某个时间范围内的数据,比如我们如果永远只关心从当前时间往前推半年内的数据特性,那么我们就不 ...

  4. POJ 3308 Paratroopers(最小点权覆盖)(对数乘转加)

    http://poj.org/problem?id=3308 r*c的地图 每一个大炮可以消灭一行一列的敌人 安装消灭第i行的大炮花费是ri 安装消灭第j行的大炮花费是ci 已知敌人坐标,同时消灭所有 ...

  5. 脑洞 博弈 E. Competitive Seagulls 2017 ACM Arabella Collegiate Programming Contest

    题目链接:http://codeforces.com/gym/101350/problem/E 题目大意:给你一个长度为n的方格,方格上面都被染色成了白色.每次染色都是选择白色的,假设目前选择的这块白 ...

  6. [整理]C语言中的a,&a和&a[0]

    #include<stdio.h> int main(void) { int a[]={1,2,3}; printf("%0X\n",a); // a的类型原本是int ...

  7. jQuery技巧笔记

    1.关于页面元素的引用 通过jquery的$()引用元素包括通过id.class.元素名以及元素的层级关系及dom或者xpath条件等方法,且返回的对象为jquery对象(集合对象),不能直接调用do ...

  8. G - Pandaland HDU - 6005 (找最小环)

    题目链接:https://cn.vjudge.net/contest/275153#problem/G 具体思路: 我们可以按照暴力的方法进行做 , 我们可以枚举每一条边,将这条边的权值设置为inf, ...

  9. Django 创建第一个Project — Django学习(二)

    检查django If Django is installed, you should see the version of your installation. If it isn’t, you’l ...

  10. python+selenium初学者常见问题处理

    要做web自动化,第一件事情就是搭建自动化测试环境,那就没法避免的要用到selenium了. 那在搭建环境和使用过程中经常会遇到以下几类问题: 1.引入selenium包失败: 出现这种错误,一般分为 ...