ZOJ 3913 积分

ZOJ 3913
题目链接:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5640
题意:
往一个立方体容器里面注水。长宽已知,高不可观。
矩阵容器里面有一些不想交的球体和立方体,大小什么的都给出来。
现要注水v升,求水平面相对于立方体容器高度。
思路:
难点在推球体积分公式啊。
其实高数学好就不会有问题,假设水平面和球体是相交的,积分符号为S,那么算出水平面和球体的距离d,则temp = S(PI*(r*r-d*d)),判断一下水平面在球体中心上还是下加个常数就可以。
当然二分的上下界写错会使劲WA这种事我是不会写的。
源码:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <iostream>
using namespace std;
const int MAXN = 100000 + 5;
const double PI = 3.1415926535897932384626433832795;
const double eps = 1e-6;
struct D
{
    double h, a, b, c;
}d[MAXN];
struct C
{
    double h, r;
}l[MAXN];
int main()
{
//    freopen("K.in", "r", stdin);
//    freopen("ZOJ 3913 WA.out", "w", stdout);
    int t;
    scanf("%d", &t);
    while(t--){
        double w, s, v;
        int n, m;
//        double sum = 0;
        double sv = 0;
        scanf("%lf%lf%lf%d%d", &w, &s, &v, &n, &m);
        for(int i = 0 ; i < n ; i++){
            scanf("%lf%lf%lf%lf", &d[i].h, &d[i].a, &d[i].b, &d[i].c);
            sv += d[i].a * d[i].b * d[i].c;
        }
        for(int i = 0 ; i < m ; i++){
            scanf("%lf%lf", &l[i].h, &l[i].r);
            sv += PI * l[i].r * l[i].r * l[i].r * 4.0 / 3.0;
        }
//        sv = sum;
            double le = v / (w * s), re = (v + sv) / (w * s);
            while(fabs(re - le) > eps){
                double mid = (re + le) / 2.0;
//                printf("re = %f, le = %f, mid = %f\n", re, le, mid);
                double sum = 0;
                for(int i = 0 ; i < n ; i++){
                    if((mid <= d[i].h + d[i].c / 2.0) && (mid >= d[i].h - d[i].c / 2.0)){
                        sum += (mid - d[i].h + d[i].c / 2.0) * d[i].a * d[i].b;
//                        printf("factor = %f\n", (mid - d[i].h + d[i].c / 2) * d[i].a * d[i].b);
                    }
                    else if(mid > d[i].h + d[i].c / 2.0)
                        sum += d[i].a * d[i].b * d[i].c;
                }
                for(int i = 0 ; i < m ; i++){
                    if((mid <= l[i].h + l[i].r) && (mid >= l[i].h - l[i].r)){
                        double u = l[i].h - mid;
                        if(u < 0)   u = -u;
                        double temp = PI*(l[i].r*l[i].r*u-u*u*u/3.0);
                        if(mid > l[i].h)  temp = temp + 2.0 * PI * l[i].r * l[i].r * l[i].r / 3.0;
                        else    temp = 2.0 * PI * l[i].r * l[i].r * l[i].r / 3.0 - temp;
//                        printf("temp = %f\n", temp);
                        sum += temp;
//                        double u = mid - (l[i].h - l[i].r);
//                        sum += PI * (l[i].r * u * u - u * u * u / 3.0);
                    }
                    else if(mid > l[i].h + l[i].r){
                        sum += l[i].r * l[i].r * l[i].r * PI * 4.0 / 3.0;
                    }
                }
                sum = w * s * mid - sum;
//                printf("sum = %.10f\n", sum);
                if(sum >= v - eps){
                    re = mid;
                }
                else
                    le = mid;
            }
            printf("%.6f\n", re);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值