zoj 3913 Bob wants to pour water(zoj 2015年10月月赛k题)

Bob wants to pour water

Time Limit: 2 Seconds       Memory Limit: 65536 KB       Special Judge

There is a huge cubiod house with infinite height. And there are some spheres and some cuboids in the house. They do not intersect with others and the house. The space inside the house and outside the cuboids and the spheres can contain water.

Bob wants to know when he pours some water into this house, what's the height of the water level based on the house's undersurface.

Input

The first line is a integer T (1 ≤ T ≤ 50), the number of cases.

For each case:

The first line contains 3 floats wl (0 < wl < 100000), the width and length of the house, v (0 < v < 1013), the volume of the poured water, and 2 integers, m (1 ≤ m ≤ 100000), the number of the cuboids, n (1 ≤ n ≤ 100000), the number of the spheres.

The next m lines describe the position and the size of the cuboids.

Each line contains z (0 < z < 100000), the height of the center of each cuboid, a (0 < a < w), b (0 < b < l), c, the width, length, height of each cuboid.

The next n lines describe the position and the size of the spheres, all these numbers are double.

Each line contains z (0 < z < 100000), the height of the center of each sphere, r (0 < 2r < w and 2r < l), the radius of each sphere.

Output

For each case, output the height of the water level in a single line. An answer with absolute error less than 1e-4 or relative error less than 1e-6 will be accepted. There're T lines in total.

Sample Input
1
1 1 1 1 1
1.5 0.2 0.3 0.4
0.5 0.5
Sample Output
1.537869
 
 
题目大意:
   
    给出一个大的立方体容器,给出长和宽,高不限,容器内放小的球体和立方体,给出他们的中心在的位置,现在往容器内放V体积水,求
 
大容器的水平面的高度。
 
 
解题思路:
   
    由于n只有10^5次方,可以直接二分,二分水面的高度就可,球被淹没的体积可以用截面法很容易算出来。
 
 
代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>

using namespace std;

double pi=3.1415926535898;
double w,l,v;
int n,m;
double ch[100010],cw[100010],cl[100010],cg[100010];
double sh[100010],sr[100010];
double av;

double getv(double h)
{
    int i;
    double ans=h*w*l;
    for(i=0;i<n;i++)
    {
        if(h>ch[i]+cg[i]/2)
        {
            ans-=cw[i]*cl[i]*cg[i];
        }
        else if(h<ch[i]-cg[i]/2)
        {
            continue;
        }
        else
        {
            ans-=cw[i]*cl[i]*(h-(ch[i]-cg[i]/2));
        }
    }
    for(i=0;i<m;i++)
    {
        if(h<=sh[i]-sr[i])
            continue;
        if(h>sh[i]+sr[i])
        {
            ans-=(4.0/3)*pi*sr[i]*sr[i]*sr[i];
        }
        else if(h>sh[i])
        {
            double hh=h-sh[i];
            ans-=hh*sr[i]*sr[i]*pi-(1.0/3)*hh*hh*hh*pi+(2.0/3)*pi*sr[i]*sr[i]*sr[i];
        }
        else if(h>sh[i]-sr[i])
        {
            double hh=sh[i]-h;
            ans-=(4.0/3)*pi*sr[i]*sr[i]*sr[i] -( hh*sr[i]*sr[i]*pi-(1.0/3)*hh*hh*hh*pi+(2.0/3)*pi*sr[i]*sr[i]*sr[i]);
        }
    }
    return ans;
}
double geth()
{
    double left=v/(w*l);
    double r=(v+av)/(w*l);

  // printf("%lf\n",l);

   // printf("%.6lf\n",av);
  //   printf("%lf %.6lf\n",left,r);
    // cout<<r-left<<endl;
   // cout<<"ok\n";
  //  cout<<l<<" "<<r<<endl;
  //int cnt=0;
  int cnt=0;
    while(cnt++<100 )
    {
        double mid=(left+r)/2;
        double now=getv(mid);
     //   cout<<mid<<endl;
     //  printf("%.6lf %.6lf\n",now,mid);
        if(now>v)
        {
            r=mid;
        }
        else
        {
            left=mid;
        }
    }
    return left;
}

int main()
{
   //freopen("D:\\in.txt","r",stdin);
    int T,i,j;
    cin>>T;
    while(T--)
    {
        av=0;
        scanf("%lf %lf %lf %d %d",&w,&l,&v,&n,&m);
        for(i=0;i<n;i++)
        {
            scanf("%lf %lf %lf %lf",&ch[i],&cw[i],&cl[i],&cg[i]);
            av+=cw[i]*cl[i]*cg[i];
        }
        for(i=0;i<m;i++)
        {
            scanf("%lf %lf",&sh[i],&sr[i]);
            av+=(4.0/3)*pi*sr[i]*sr[i]*sr[i];
        }
        printf("%.6lf\n",geth());
    }
}


    


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值