POJ_1434_Fill the Cisterns!

                                     Fill the Cisterns!
                           Time Limit: 5000M        Memory Limit: 10000K
                           Total Submissions: 4016      Accepted: 1331

Description

During the next century certain regions on earth will experience severe water shortages. The old town of Uqbar has already started to prepare itself for the worst. Recently they created a network of pipes connecting the cisterns that distribute water in each neighbourhood, making it easier to fill them at once from a single source of water. But in case of water shortage the cisterns above a certain level will be empty since the water will to the cisterns below.

这里写图片描述

You have been asked to write a program to compute the level to which cisterns will be lled with a certain volume of water, given the dimensions and position of each cistern. To simplify we will neglect the volume of water in the pipes.

Task

Write a program which for each data set:

reads the description of cisterns and the volume of water,

computes the level to which the cisterns will be filled with the given amount of water,

writes the result.
Input

The first line of the input contains the number of data sets k, 1 <= k <= 30. The data sets follow.

The first line of each data set contains one integer n, the number of cisterns, 1 <= n <= 50 000. Each of the following n lines consists of 4 nonnegative integers, separated by single spaces: b, h, w, d - the base level of the cistern, its height, width and depth in meters, respectively. The integers satisfy 0 <= b <= 10^6 and 1 <= h * w * d <= 40 000. The last line of the data set contains an integer V - the volume of water in cubic meters to be injected into the network. Integer V satisfies 1 <= V <= 2 * 10^9.
Output

The output should consist of exactly d lines, one line for each data set.

Line i, 1 <= i <= d, should contain the level that the water will reach, in meters, rounded up to two fractional digits, or the word ‘OVERFLOW’, if the volume of water exceeds the total capacity of the cisterns.
Sample Input

3
2
0 1 1 1
2 1 1 1
1
4
11 7 5 1
15 6 2 2
5 8 5 1
19 4 8 1
132
4
11 7 5 1
15 6 2 2
5 8 5 1
19 4 8 1
78
Sample Output

1.00
OVERFLOW
17.00
Source

Central Europe 2001

题意大概是空间中有n个长方体蓄水池,每个蓄水池底部用细管连接(细管中水的体积忽略不计),给出所有蓄水池底面离地高度及其长宽高,再给定V升水,求水位高度(相对地面),如果V超过所有蓄水池总体积则溢出,这里不要误解,如例图中位于下方的储满水的蓄水池不会溢出 相当于其上有盖,这里的溢出是指往蓄水池注水时的溢出。

题解:首先算出蓄水池总体积,小于V则溢出,否则利用二分找水位点,水位点一定位于最低的蓄水池地面和最高的一个蓄水池顶面(注意,是其基面高度加蓄水池高度最高才算最高,在这wa了…..)

代码如下:

#include <iostream>
#include <iomanip>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <list>
#include <stack>
#include <deque>
#include <queue>
#include <vector>
#include <algorithm>
#include <functional>

#define debug(x) cout << "--------------> " << x << endl

using namespace std;

const double PI = acos(-1.0);
const double eps = 1e-4;
const long long INF = 0x7fffffff;
const long long MOD = 1000000007;
const int MAXN = 50088;

int n;

class DIM
{
public:
    double b, h, w, d;     //base level, height, width, depth
}dim[MAXN];

bool cmp(DIM a, DIM b)
{
    return a.b < b.b;
}

double getSumV(double lev)    //水位为lev时储水器中水的总体积
{
    double sumVa = 0;
    for(int i = 0; i < n; ++i)
    {
        if( lev - dim[i].b > eps)
        sumVa += lev - dim[i].b - dim[i].h > eps ? dim[i].h * dim[i].w * dim[i].d : (lev - dim[i].b) * dim[i].w * dim[i].d;
        else
            break;
    }
    return sumVa;
}

int main()
{
    int t;
    scanf("%d", &t);
    double V, sumV, lev;
    while(t--)
    {
        sumV = lev = 0;
        scanf("%d", &n);
        for(int i = 0; i < n; ++i)
        {
            scanf("%lf %lf %lf %lf", &dim[i].b, &dim[i].h, &dim[i].w, &dim[i].d);
            sumV+= dim[i].h * dim[i].w * dim[i].d;
            lev = max(lev, dim[i].b + dim[i].h);
        }
        sort(dim, dim+n, cmp);
        //    sort(dim, dim+n, cmp);  //按base level 升序排序
        scanf("%lf", &V);
        if(V - sumV > eps)
        {
            printf("OVERFLOW\n");
            continue;
        }
        double l = dim[0].b, r = lev, mid;
        while(r-l >= eps)
        {
            mid = (l + r) / 2.0;
            if(V - getSumV(mid) <= eps)
                r = mid-1e-4;
            else
                l = mid+1e-4;
        }
       printf("%.2f\n", mid);

    }
     return 0;
}

/***************
   欢迎交流指正
    不胜感激!
***************/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值