zoukankan      html  css  js  c++  java
  • luogu P4207 [NOI2005]月下柠檬树

    luogu

    为了方便,设树顶的那一点为一个半径为0的圆

    首先我们把所有圆投影到平面上,然后得到的图形应该是一堆圆心在(x)轴上的圆+相邻两个圆公切线构成的梯形的并,我们可以只计算上面一半的面积然后乘2.因为上面一半的轮廓线不规则,考虑自适应Simpson求轮廓线和(x)轴围成的面积.现在的问题是求出某一个横坐标上与(x)轴垂直的直线和轮廓线的交点纵坐标,因为这个轮廓线是圆和公切线的并,那么我们只要枚举所有圆和公切线,然后对于这些图形在(x)处的纵坐标取最大值即可

    至于圆的公切线,这可以把两个圆的半径同时减去较小的半径,然后就变成圆和点的切线,可以用一些(sincos)等算出来,最后平移回原位置即可

    #include<bits/stdc++.h>
    #define LL long long
    #define db double
    
    using namespace std;
    const int N=500+10;
    const db pi=acos(-1),eps=1e-10;
    int rd()
    {
        int x=0,w=1;char ch=0;
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
        return x*w;
    }
    int n;
    db gg,h[N],r[N],li[N][2],ps[N][2];
    db sq(db x){return x*x;}
    db f(db x)
    {
        db an=0;
        for(int i=1;i<n;++i)
    	if(x>ps[i][0]-eps&&x<ps[i][1]+eps) an=max(an,li[i][0]*x+li[i][1]);
        for(int i=1;i<=n;++i)
        {
    	    if(fabs(x-h[i])>r[i]-eps) continue;
        	an=max(an,sqrt(sq(r[i])-sq(fabs(x-h[i]))));
        }
        return an;
    }
    db g(db l,db r){return (f(l)+4*f((l+r)/2)+f(r))/6*(r-l);}
    db cal(db l,db r,db s)
    {
        db mid=(l+r)/2,s1=g(l,mid),s2=g(mid,r);
        if(fabs(s-s1-s2)<eps) return s;
        return cal(l,mid,s1)+cal(mid,r,s2);
    }
    
    int main()
    {
    //be careful of details
        n=rd()+1;
        scanf("%lf",&gg),gg=1/tan(gg);
        for(int i=1;i<=n;++i) scanf("%lf",&h[i]),h[i]=h[i]*gg+h[i-1];
        for(int i=1;i<n;++i) scanf("%lf",&r[i]);
        for(int i=1;i<n;++i)
        {
        	if(fabs(r[i]-r[i+1])<eps)
        	{
        	    li[i][0]=0,li[i][1]=r[i],ps[i][0]=h[i],ps[i][1]=h[i+1];
        	    continue;
        	}
        	db nx=0,ny=abs(r[i]-r[i+1]),xx=nx,yy=ny;
        	db a1=acos(ny/(h[i+1]-h[i])),ag=pi/2-a1,nk,nb;
        	if(r[i]>r[i+1])
        	{
        	    nx=xx*cos(ag)+yy*sin(ag),ny=yy*cos(ag)-xx*sin(ag);
        	    nk=-ny/(h[i+1]-h[i]-nx),nb=-nk*h[i+1]+r[i+1]*(sin(a1)-nk*sin(ag));
        	}
        	else
        	{
        	    nx=xx*cos(ag)-yy*sin(ag),ny=yy*cos(ag)+xx*sin(ag);
        	    nk=ny/(h[i+1]+nx-h[i]),nb=-nk*h[i]+r[i]*(sin(a1)+nk*sin(ag));
        	}
        	db dx=r[i]*sin(ag)*(r[i]<r[i+1]?-1:1),d2=r[i+1]*sin(ag)*(r[i]<r[i+1]?-1:1);
        	li[i][0]=nk,li[i][1]=nb;
        	if(fabs(min(r[i],r[i+1]))>eps) ps[i][0]=h[i]+dx,ps[i][1]=h[i+1]+d2;
        	else if(fabs(r[i])<eps) ps[i][0]=h[i],ps[i][1]=h[i+1]+nx;
        	else ps[i][0]=h[i]+nx,ps[i][1]=h[i+1];
        }
        db ql=1e9,qr=-1e9;
        for(int i=1;i<=n;++i) ql=min(ql,h[i]-r[i]),qr=max(qr,h[i]+r[i]);
        printf("%.2lf
    ",cal(ql,qr,g(ql,qr))*2);
        return 0;
    }
    
  • 相关阅读:
    浅入浅出EmguCv(一)OpenCv与EmguCv
    Selenium2入门(三)WebDriver API之Get
    Selenium2入门(二)WebDriver
    Selenium2入门(一)简介
    Tomcat部署Solr4.10.4
    On the Optimal Approach of Survivable Virtual Network Embedding in Virtualized SDN
    几篇虚拟映射文章粗读
    SDN网络虚拟化中有效协调的映射算法
    SDN网络中hypervisor带来的控制器时延(Hypervisor位置的优化)
    FlowerVisor理解
  • 原文地址:https://www.cnblogs.com/smyjr/p/12391894.html
Copyright © 2011-2022 走看看