• Luogu P4207 [NOI2005]月下柠檬树


    Link
    可以发现投影是一些圆,相邻的两个圆之间有一个由两个外公切线构成的梯形。
    不难发现投影关于(x)轴对称,因此只需要求出上半部分的面积。
    那么我们先求出所有相邻两圆的外公切线中上方的一条,然后自适应Simpson积分即可。

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    typedef double db;
    const int N=507;const db eps=1e-10,pi=acos(-1);
    int n,m;db t,L=1e10,R=-1e10;
    struct line
    {
        db l,r,k,b;
        void init(db x1,db y1,db x2,db y2){l=x1,r=x2,k=(y2-y1)/(x2-x1),b=y1-k*x1;}
        db f(db x){return k*x+b;}
    }l[N];
    struct circle{db x,r;}c[N];
    db f(db x)
    {
        db h=0;
        for(int i=1;i<=m;++i) if(l[i].l-eps<x&&x<l[i].r+eps) h=std::max(h,l[i].f(x));
        for(int i=1;i<=n;++i)
        {
    	db d=fabs(x-c[i].x);
    	if(d-eps<c[i].r) h=std::max(h,sqrt(c[i].r*c[i].r-d*d));
        }
        return h;
    }
    db g(db l,db r){return (f(l)+f(r)+4*f((l+r)/2))/6*(r-l);}
    db cal(db l,db r){db v=g(l,r),mid=(l+r)/2;return fabs(g(l,mid)+g(mid,r)-v)<eps? v:cal(l,mid)+cal(mid,r);}
    int main()
    {
        scanf("%d%lf",&n,&t),t=1/tan(t),++n;
        for(int i=1;i<=n;++i) scanf("%lf",&c[i].x),c[i].x=c[i-1].x+c[i].x*t;
        for(int i=1;i<n;++i) scanf("%lf",&c[i].r);
        for(int i=1;i<=n;++i) L=std::min(L,c[i].x-c[i].r),R=std::max(R,c[i].x+c[i].r);
        for(int i=1;i<n;++i)
        {
    	db len=c[i+1].x-c[i].x,si,co;
    	if(len+eps>fabs(c[i+1].r-c[i].r)) si=(c[i].r-c[i+1].r)/len,co=sqrt(1-si*si),l[++m].init(c[i].x+c[i].r*si,c[i].r*co,c[i+1].x+c[i+1].r*si,c[i+1].r*co);
        }
        printf("%.2lf",2*cal(L,R));
    }
    
  • 相关阅读:
    python 代码规范
    Helm 入门指南
    思路和决断
    awk替换第几行第几列的值
    一个awk命令的demo
    装饰模式
    Java多线程Thread.yield(),thread.join(), Thread.sleep(200),Object.wait(),Object.notify(),Object.notifyAll()的区别
    类继承时,构造函数和析构函数的调用次序
    C++中delete和 delete[]的区别
    回溯
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12342822.html
Copyright © 2020-2023  润新知