Bzoj1502【NOI2005】月下柠檬树

自适应Simpson积分求面积并。
平行光啊,它有个好,照下来那影子和原来平行于地面的物体是全等。于是我们就有了横向排布着的一些圆和一些线段,然后算就好了。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 550;
const int INF  = 0x3f3f3f3f;
#define EPS  1e-6
struct Circle {
    double x,R;
}C[maxn];
struct Line {
    double k,b;
    double L,R;
}line[maxn];int lines=0;
int cnt;
int n;double alpha,L,R;
double F(double x) {
    double ret = 0;
    for(int i = 1; i <= lines; i++) {
        if( x >= line[i].L && x <= line[i].R ) 
            ret = max( ret, line[i].k * x + line[i].b );
    }
    for(int i = 1; i <= n; i++ ) {
        if( x >= C[i].x-C[i].R && x <= C[i].x + C[i].R ) {
            ret = max( ret , sqrt ( C[i].R * C[i].R - (x-C[i].x)*(x-C[i].x) ) );
        }
    }
    return ret;
}
double Simpson(double L,double R,double mid,double FL,double FR,double FM) {
    double tFL = F( (L+mid)/2), tFR = F((mid+R)/2);
    double ans = (R-L)*(FL+FR+4*FM)/6;
    double Lans = (mid-L)*(FL+FM+4*tFL)/6;
    double Rans = (R-mid)*(FM+FR+4*tFR)/6;
    if (fabs(Lans+Rans-ans) < EPS ) return ans;
    return Simpson(L,mid,(L+mid)/2,FL,FM,tFL) + Simpson(mid,R,(mid+R)/2,FM,FR,tFR);
}
int main() {
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);

    scanf("%d%lf",&n,&alpha);n++;
    alpha = 1.0 / tan(alpha);
    C[0].x=0;
    for(int i = 1; i <= n; i++) {
        double x;
        scanf("%lf",&x);
        C[i].x = C[i-1].x + x * alpha;
    }
    L=INF;R=-INF;
    for(int i = 1; i <= n; i++) {
        scanf("%lf",&C[i].R);
        L = min(L, C[i].x - C[i].R);
        R = max(R, C[i].x + C[i].R);
    }
    for(int i = 1; i < n; i++) {
        if( C[i+1].x-C[i].x - fabs(C[i+1].R-C[i].R) < EPS )  continue;

        lines++;
        double sina = ( C[i].R - C[i+1].R) / ( C[i].x - C[i+1].x);
        double cosa = sqrt(1.0 - sina*sina);
        double tana = sina / cosa;
        line[lines].L = C[i].x - C[i].R * sina;
        line[lines].R = C[i+1].x - C[i+1].R * sina;
        line[lines].k = tana;
        line[lines].b = C[i].R  * cosa - line[lines].L * tana;
    }
    printf("%.2lf\n",2*Simpson(L,R,(L+R)/2.0,0,0,F((L+R)/2.0)));


}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值