1502: [NOI2005]月下柠檬树

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit:
1017  Solved: 562
[Submit][Status][Discuss]

Description

Input

文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度)。第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的高度和每层的高度。第3行包含n个实数r1,r2,…,rn,表示柠檬树每层下底面的圆的半径。上述输入文件中的数据,同一行相邻的两个数之间用一个空格分隔。输入的所有实数的小数点后可能包含1至10位有效数字。

Output

输出1个实数,表示树影的面积。四舍五入保留两位小数。

Sample Input

2 0.7853981633
10.0 10.00
10.00
4.00 5.00

Sample Output

171.97

HINT

1≤n≤500,0.3

Source

Solution

一道计算集合比较蛋疼的题目

当时的正解应该是分类讨论+特判很多东西再直接求面积,但是发现这题非常适合辛普森积分所以就直接上了

那么先是辛普森积分的公式:

对于某些不易计算曲线的一种近似方法,能自动调整精度,但误差较大(比较平滑的曲线非常适合)

具体的计算流程就是,计算[l,mid]以及[mid,r]与直接计算[l,r]的结果相比较,如果近似则返回[l,r]即可,否则可以分别递归细化

这种做法非常好卡,一种最简单的卡法:这样一开始就会直接返回,然而递归下去才能求的更精确的值

---------------------------------------------------分割线---------------------------------------------------

首先我们考虑这题的投影,圆投下来,和之前完全一样,所以投影本质是一些圆和他们的公切线组成的图形求面积

发现其实是轴对称图形,所以可以考虑直接利用扫描线+自适应Simpson来做

扫描线被覆盖部分的长度的函数F(x)在这个图形的区间中是连续的,因此不必考虑将整个图形拆成若干个一坨一坨的图形再求积分,少了不少细节。

无论扫描线在何处,它被覆盖的部分也是永远是连续的,因此可以暴力找每个圆是否和扫描线有交,每条公切线段是否和扫描线有交,然后取扫描线被覆盖长度的最大值即可

那么至于求公切线,比较简单,给出详细方法:

首先我们得到:$l=C_{i+1}.O.x-C_{i+1}.O.x$
那么我们可以算出:$sin\alpha = (R-r)/l$,$cos\alpha = \sqrt{1-sin^2\alpha}$(考虑从$C_{i+1}.O$向$R$做垂线)
那么可以算出切点:

$C_{i}.A=(C_{i}.O.x+R*sin\alpha,R*cos\alpha)$
$C_{i+1}.A=(C_{i+1}.O.x+r*sin\alpha,r*cos\alpha)$

这题的细节比较麻烦,注意特判圆被另一个圆直接覆盖的情况

---------------------------------------------------分割线---------------------------------------------------

这道题还需要注意一下精度问题

个人测试:eps=1e-5是可行最优

eps=1e-12   --> 5s

eps=1e-8     --> 1s

eps=1e-5     --> 0.5s

eps=1e-3/-4 --> Wrong_Answer

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
#define MAXN 1010
double alpha;
int N,num;
#define INF 1e12
#define eps 1e-5
struct Point
{
double x,y;
Point (double X=,double Y=) {x=X; y=Y;}
};
struct Circle
{
double r;
Point c;
Circle(Point C=(Point){,},double R=) {c=C; r=R;}
}C[MAXN];
struct Line
{
Point s,t;
double k,b;
Line(Point S=(Point){,},Point T=(Point){,})
{
s=S,t=T;
if (s.x>t.x) swap(s,t);
k=(s.y-t.y)/(s.x-t.x);
b=s.y-k*s.x;
}
double f(double x) {return k*x+b;}
}l[MAXN];
int dcmp(double x) {if (fabs(x)<eps) return ; return x<? -:;}
double F(double x)
{
double re=;
for (int i=; i<=N; i++) //枚举圆是否与扫描线有交
{
double d=fabs(x-C[i].c.x);
if (dcmp(d-C[i].r)>) continue;
double len=*sqrt(C[i].r*C[i].r-d*d);
re=max(re,len);
}
for (int i=; i<=num; i++) //枚举公切线
if (x>=l[i].s.x && x<=l[i].t.x) re=max(re,*l[i].f(x));
return re;
} //利用扫描线去判断
double Calc(double l,double r) {double mid=(l+r)/; return (F(l)+F(r)+F(mid)*)*(r-l)/;}
double Simpson(double l,double r,double now)
{
double mid=(l+r)/;
double x=Calc(l,mid),y=Calc(mid,r);
if (!dcmp(now-x-y)) return now;
else return Simpson(l,mid,x)+Simpson(mid,r,y);
}
void Solve()
{
double L=INF,R=-INF;
for (int i=; i<=N+; i++)
L=min(L,C[i].c.x-C[i].r),R=max(R,C[i].c.x+C[i].r);
// printf("%lf\n%lf\n",L,R);
for (int i=; i<=N; i++)
{
double d=C[i+].c.x-C[i].c.x;
if (dcmp(d-fabs(C[i].r-C[i+].r))<) continue; //特判小圆被大圆覆盖的情况
double sina=(C[i].r-C[i+].r)/d,cosa=sqrt(-sina*sina);
l[++num]=(Line){(Point){C[i].c.x+C[i].r*sina,C[i].r*cosa},(Point){C[i+].c.x+C[i+].r*sina,C[i+].r*cosa}};
}
printf("%.2lf\n",Simpson(L,R,Calc(L,R)));
}
int main()
{
scanf("%d%lf",&N,&alpha);
double h,r;
for (int i=; i<=N+; i++)
scanf("%lf",&h),
C[i]=(Circle){((Point){(h/tan(alpha))+C[i-].c.x,}),};
for (int i=; i<=N; i++)
scanf("%lf",&r),C[i].r=r;
// for (int i=1; i<=N+1; i++)
// printf("%d %.2lf %.2lf\n",i,C[i].c.x,C[i].r);
Solve();
return ;
}

晚上颓这道‘模版题’简直不要太爽,来个人求一下我的心里阴影面积吧QAQ

【BZOJ-1502】月下柠檬树 计算几何 + 自适应Simpson积分的更多相关文章

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

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

  2. BZOJ 1502 月下柠檬树(simpson积分)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1502 题意:给出如下一棵分层的树,给出每层的高度和每个面的半径.光线是平行的,与地面夹角 ...

  3. BZOJ 1502 月下柠檬树(simpson积分)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1502 题意:给出如下一棵分层的树,给出每层的高度和每个面的半径.光线是平行的,与地面夹角 ...

  4. bzoj 1502 月下柠檬树【Simpson积分】

    投影到地面之后,会发现圆形在平行光下面积和形状是不会变的,也就是所要求的图形是若干个圆和把相邻两个圆连起来的公切线所组成的. 公切线和圆间距瞎求一下就行,注意要去掉被完全覆盖的圆 然后simpson即 ...

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

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

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

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

  7. [日常摸鱼]bzoj1502[NOI2005]月下柠檬树-简单几何+Simpson法

    关于自适应Simpson法的介绍可以去看我的另一篇blog http://www.lydsy.com/JudgeOnline/problem.php?id=1502 题意:空间里圆心在同一直线上且底面 ...

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

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

  9. 【bzoj1502】[NOI2005]月下柠檬树 自适应Simpson积分

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

随机推荐

  1. Android fragment之间消息传递

    1. 在Fragment里定义一个内部接口, 在Fragment初始化方法里, 把父Activity转换成这个接口, 赋值给成员变量 public class DummyFragment extend ...

  2. Java核心技术点之反射

    1. 概述 Java 反射是可以让我们在运行时获取类的方法.属性.父类.接口等类的内部信息的机制.也就是说,反射本质上是一个“反着来”的过程.我们通过new创建一个类的实例时,实际上是由Java虚拟机 ...

  3. Java 集合系列07之 Stack详细介绍(源码解析)和使用示例

    概要 学完Vector了之后,接下来我们开始学习Stack.Stack很简单,它继承于Vector.学习方式还是和之前一样,先对Stack有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它. ...

  4. Codevs 1229 数字游戏

    1229 数字游戏  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 白银 Silver     题目描述 Description Lele 最近上课的时候都很无聊,所以他发明了 ...

  5. [转]spring 注入静态变量

    原文: http://www.cnblogs.com/xing901022/p/4168124.html 今天碰到一个问题,我的一个工具类提供了几种静态方法,静态方法需要另外一个类的实例提供处理,因此 ...

  6. 批量修改string中的字符

    #1,修改"/"为"\\",多用于在txt读取内容后进行修改 size_t pos0 = mkfolder.find("/");//首次查找 ...

  7. c语言中%s与%c对读入字符串的区别

    对于scanf函数,需求%s类型时,\n是不会影响scanf内容的对于需求%c类型时,\n也是字符,自然会有影响.

  8. Android -- Apk安装简诉

    安装涉及到如下几个目录 system/app  ​ 系统自带的应用程序,无法删除 data/app   用户程序安装的目录,有删除权限. 安装时把apk文件复制到此目录 ​ data/data  存放 ...

  9. web性能优化——浏览器相关

    简介 优化是一个持续的过程.所以尽可能的不要有人为的参与.所以能自动化的或者能从架构.框架级别解决的就最更高级别解决. 这样即能实现面对开发人员是透明的.不响应,又能确保所有资源都是被优化过的. 场景 ...

  10. 关于.Net的面试遐想

    概述 这几天更新相关的面试题目,主是要针对有4年或以上经验的面试者,总体来说,发现面试人员的答题效果和预期相差比较大,我也在想是不是我出的题目偏离现实,但我更愿意相信,是我们一些.Net开发者在工作中 ...