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

关于自适应Simpson法的介绍可以去看我的另一篇blog

http://www.lydsy.com/JudgeOnline/problem.php?id=1502

题意:空间里圆心在同一直线上且底面与地面平行的若干个圆台和顶层的圆锥以$\alpha$的角度投影到地面,求投影的面积。



(其实我是看po姐博客来的x)

首先把圆锥的顶点也看成一个半径为0的圆满,对于每个高度为$h$的圆投影下去的坐标是$h/tan(\alpha)$,半径不变,而对于圆台的侧面投影下去是上下底两个圆的切线。

关于两个圆的切线可以像图上这样求(参考po姐博客的x)

$\sin(\alpha)=\frac{r_{i-1}-r_i}{x_i-x_{i-1}}$

这个式子同样可以适用于其他情况,然后三角函数搞一下求出其他点的坐标,根据坐标的范围用Simpson法来求面积。

只是把求点的函数值改成扫一遍所有的点和圆,找最大值。

哦然后我的Simpson递归的时候本来是让eps乘上$\frac{1}{2}$的…但是这样会T掉,不乘又会wa…orz

然后改成$\frac{2}{3}$就可以了…跑900+ms真神奇

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=515;
struct point
{
    double x,y;
};
struct line
{
    point p1,p2;
    double k,b;
    line(){}
    void modify(double x1,double y1,double x2,double y2)
    {
        p1.x=x1;p1.y=y1;
        p2.x=x2;p2.y=y2;
        k=(p1.y-p2.y)/(p1.x-p2.x);
        b=p1.y-k*p1.x;
    }
    double f(double x)
    {
        return k*x+b;
    }
}ls[N];
struct circle
{
    double x,r;
}cs[N];
int n,tot;double alpha;
inline double f(double x)
{
    double res=0;double eps=1e-6;
    for(register int i=1;i<=n;i++)
    {
        double dis=fabs(x-cs[i].x);
        if(dis-cs[i].r>-eps)continue;
        double y=sqrt(cs[i].r*cs[i].r-dis*dis);
        res=max(res,y);
    }
    for(register int i=1;i<=tot;i++)
    {
        if(!(ls[i].p1.x<=x&&x<=ls[i].p2.x))continue;
        double y=ls[i].f(x);
        res=max(res,y);
    }
    return res;
}
inline double calc(double l,double r)
{
    double mid=l+(r-l)/2;
    return (f(l)+4.0*f(mid)+f(r))*(r-l)/6.0;
}
inline double asr(double l,double r,double area,double eps)
{
    double mid=l+(r-l)/2;
    double L=calc(l,mid),R=calc(mid,r);
    if(fabs(L+R-area)<=eps*10.0)return L+R+(L+R-area)/10.0;
    return asr(l,mid,L,eps*2.0/3.0)+asr(mid,r,R,eps*2.0/3.0);
}
inline double solve(double l,double r,double eps)
{
    return asr(l,r,calc(l,r),eps);
}
int main()
{
    //freopen("input.in","r",stdin);
    double eps=1e-6,l,r;l=r=0;
    scanf("%d%lf",&n,&alpha);alpha=1/(tan(alpha));
    for(register int i=1;i<=n+1;i++)
    {
        scanf("%lf",&cs[i].x);
        cs[i].x*=alpha;
        cs[i].x+=cs[i-1].x;
    }
    for(register int i=1;i<=n;i++)
    {
        scanf("%lf",&cs[i].r);
    }
    for(register int i=1;i<=n+1;i++)
    {
        l=min(l,cs[i].x-cs[i].r);
        r=max(r,cs[i].x+cs[i].r);
    }
    for(register int i=2;i<=n+1;i++)
    {
        double L=cs[i].x-cs[i-1].x;
        if(L-fabs(cs[i].r-cs[i-1].r)<eps)continue;
        //double sin_alpha=fabs(cs[i].r-cs[i-1].r)/L;
        double sin_alpha=(cs[i-1].r-cs[i].r)/L;
        double cos_alpha=sqrt(1-sin_alpha*sin_alpha);
        ls[++tot].modify(cs[i-1].x+cs[i-1].r*sin_alpha,cs[i-1].r*cos_alpha,
                       cs[i].x+cs[i].r*sin_alpha,cs[i].r*cos_alpha);
    }
    printf("%.2lf",solve(l,r,eps)*2.0);
    return 0;
}

原文地址:https://www.cnblogs.com/yoooshinow/p/8185614.html

时间: 2024-08-26 22:55:49

[日常摸鱼]bzoj1502[NOI2005]月下柠檬树-简单几何+Simpson法的相关文章

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

1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1169  Solved: 626[Submit][Status][Discuss] Description Input 文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度).第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的高度和每层的高度.第3行包含n个实数r1,r2,…,rn,表示柠檬树每层下底面的

【BZOJ-1502】月下柠檬树 计算几何 + 自适应Simpson积分

1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1017  Solved: 562[Submit][Status][Discuss] Description Input 文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度).第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的高度和每层的高度.第3行包含n个实数r1,r2,…,rn,表示柠檬树每层下底面的

[BZOJ 1502][NOI2005]月下柠檬树(自适应Simpson积分)

Description 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树旁,独自思索着人生的哲理. 李哲是一个喜爱思考的孩子,当他看到在月光的照射下柠檬树投在地面上的影子是如此的清晰,马上想到了一个问题:树影的面积是多大呢? 李哲知道,直接测量面积是很难的,他想用几何的方法算,因为他对这棵柠檬树的形状了解得非常清楚,而且想好了简化的方法. 李哲将整棵柠檬树分成了 n 层,由下向上依次将层编号为 1,2,...,n.从第

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

[BZOJ1502][NOI2005]月下柠檬树 Description 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树旁,独自思索着人生的哲理.李哲是一个喜爱思考的孩子,当他看到在月光的照射下柠檬树投在地面上的影子是如此的清晰,马上想到了一个问题:树影的面积是多大呢?李哲知道,直接测量面积是很难的,他想用几何的方法算,因为他对这棵柠檬树的形状了解得非常清楚,而且想好了简化的方法.李哲将整棵柠檬树分成了n 层,由下向

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

1502: [NOI2005]月下柠檬树 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1070  Solved: 596[Submit][Status][Discuss] Description Input 文件的第1行包含一个整数n和一个实数alpha,表示柠檬树的层数和月亮的光线与地面夹角(单位为弧度).第2行包含n+1个实数h0,h1,h2,…,hn,表示树离地的高度和每层的高度.第3行包含n个实数r1,r2,…,rn,表示柠檬树每层下底面的

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

https://www.lydsy.com/JudgeOnline/problem.php?id=1502 https://www.luogu.org/problemnew/show/P4207 李哲非常非常喜欢柠檬树,特别是在静静的夜晚,当天空中有一弯明月温柔地照亮地面上的景物时,他必会悠闲地坐在他亲手植下的那棵柠檬树旁,独自思索着人生的哲理.李哲是一个喜爱思考的孩子,当他看到在月光的照射下柠檬树投在地面上的影子是如此的清晰,马上想到了一个问题:树影的面积是多大呢?李哲知道,直接测量面积是很难

BZOJ 1502 NOI2005 月下柠檬树 Simpson自适应公式

题目大意:给定一棵由圆台和圆锥构成的柠檬树,月光以α的夹角平行射向地面,求阴影部分面积 补充题目大意:看到这题我产生了心理阴影,求阴影部分面积 题目不好分析,但其实就是求一堆圆和一堆梯形的面积交 样例如图(画的有点烂),将顶点看做半径为0的圆,则图中圆的半径即为给定圆的半径,圆心距为h/tan(α),直线为两圆公切线 这题我们采用辛普森自适应公式 首先辛普森公式见度受百科 http://baike.baidu.com/view/2710883.htm?fr=aladdin 比较遗憾的是 辛普森公

BZOJ 1502 [NOI2005]月下柠檬树 自适应Simpson积分

题意:链接 方法:自适应Simpson积分 解析: 大半夜刷这道题真是爽歪歪. 求一棵树(圆锥加圆台组成)在平面上的投影的面积. 给定投影角度(0.3 < alpha <= pi/2). 先来想想圆的投影是什么样子 还是他自己. 再想圆锥投影是什么样子 一个点加一个圆,并且有这个点与该圆的两条切线(该点在圆内部时没有切线) 再想圆台 两个圆,加上两个圆的外公切线组成的一坨图形. 不妨随意画一个. 好难画- -! 大概就转化成这个样子了. 观察这个图形- 轴对称啊- -! 这意味着我们好多东西都

[日常摸鱼][poj2777]Count Color-线段树

辣鸡会考考完啦哈哈哈哈 题意:一块板分成$L$块,每次给一段连续的块染色或者询问一段有几种颜色,颜色的范围$\leq 30$ 我记得我好像做过一个类似的二维染色的问题-不过那个用树状数组直接过掉了- 这题颜色范围这么小的范围直接想到线段树了吧,直接把一个区间的颜色二进制按位压缩成一个状态,维护区间或 题面还特地说了可能$a>b$-然而我没看到 #include<cstdio> const int N=100005; inline int read() { int s=0,f=1;char