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;
}
/***************
欢迎交流指正
不胜感激!
***************/