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. C# Math类简介

    Math.abs() 计算绝对值. Math.acos() 计算反余弦值. Math.asin() 计算反正弦值. Math.atan() 计算反正切值. Math.atan2() 计算从x 坐标轴到 ...

  2. Oracle 常见错误排查

    1. java.sql.SQLException: ORA-01000: 超出打开游标的最大数 step 1: 查看数据库当前的游标数配置slqplus:show parameter open_cur ...

  3. opencv8-GPU之相似性计算

    Opencv支持GPU计算,并且包含成一个gpu类用来方便调用,所以不需要去加上什么__global__什么的很方便,不过同时这个类还是有不足的,待opencv小组的更新和完善. 这里先介绍在之前的& ...

  4. 读懂IL代码就这么简单(二)

    一 前言 IL系列 第一篇写完后 得到高人指点,及时更正了文章中的错误,也使得我写这篇文章时更加谨慎,自己在了解相关知识点时,也更为细致.个人觉得既然做为文章写出来,就一定要保证比较高的质量,和正确率 ...

  5. JS事件详解

    hello,我是沐晴,最近呢,来总结一下 JS中的常用的事件,希望我们都能一起查漏补缺. 焦点事件 焦点事件在表单中经常用到,那什么是焦点呢?比如我们文本框里面的有光标的时候,就是获得了焦点,我们就可 ...

  6. 3到6年的.NETer应该掌握哪些知识?

    我们组的开发人力一直比较紧张,今年春节后,高层终于给了几个headcount,我们可以开始招人了.从三月初我们就开始找简历,渠道有拉钩,内推,我司自己的招聘网站和智联等.简历筛了很多,也打了很多电话, ...

  7. .Net 程序集按需加载机制

    在开始本文之前先提两个疑问: 1.一个.Net程序依赖很多的dll,那个他们是在应用程序启动的时候全部把所依赖的动态库全部都加载到应用程序域中的呢还是有选择的加载呢? 2.当应用程序已经启动后我们动态 ...

  8. 千呼万唤岂出来,写款软件不容易——Visual Entity 2.0 发布

    在各位用户不继的催更中,终于完成了这次更新.Visual Entity这个软件发布于 2011年,这个软件完成后,便上班去了,也没有做什么推广工作.所以知道的用户并不多,尽管它是个非常好用.并且免费的 ...

  9. 在线程中调用SaveFileDialog

    在多线程编程中,有时候可能需要在单独线程中执行某些操作.例如,调用SaveFileDialog类保存文件.首先,我们在Main方法中创建了一个新线程,并将其指向要执行的委托SaveFileAsyn.在 ...

  10. java中的URLConnection

    *URLConnection是个抽象类,它有两个直接子类分别是HttpURLConnection和JarURLConnection.另外一个重要的类是URL,通常URL可以通过传给构造器一个Strin ...