POJ1434 Fill the Cisterns! 二分法

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

题意是若干个长方体,每个的长宽高和离地距离各不相同但是相互联通,有一定量的水,求水平面在哪,或者溢出。有n组数据,每组表示若干个长方体的离地距离,长、宽、高,和总的水量。
二分法
大致思路是,如果总的水量大于所有长发体的体积和,那么就溢出。否则,水平面就会在离地距离最低的一个长发体的底到最高的一个长方体顶面之间。也就是二分的上下界。对于每个mid,遍历每一个长方体,通过计算当前mid下,这个长方体内水量,并累加求得所有长方体内水量的和。如果总和大于等于总的水量,说明这个mid有效,尝试更小的mid,ri=mid,直到正好求得水位。如果总和小于总水量,说明mid太低,尝试更大的mid,le=mid。

遇到的问题
eps,在两个double进行比较的时候,必需加上这个值,一般设置为需要的精度以下。
在输入和输出时,尽量避免使用cin和cout,因为效率低,近多用scanf和printf。在输出字符串时,可以使用puts(“OVERFLOW”);自带换行。
在输入时当要记录最大值与最小值时,尽量避免使用()?:表达式,不直观,而应当使用min和max函数,在头文件cmath中。
因为le和ri的值,在每一次中都需要重置,所以应当将其初始化放入外层while中。
内层while中,因为对于每一个mid,都要遍历每个长方体。因为mid是动态变化的,所以会出现mid低于当前长方体离地高度的情况。故需要用if(mid-a[i].b>=0)来判断当前mid是否比其离地距离高,如果低,则不执行任何操作。
因为double型。所以在确定新的上下界时,le=mid和ri=mid,不用+1-1。
对于确定每一次可行的mid之后,这个可行的值就赋给了ri,而对于并不确定的下一次情况,mid和le的值都可能改变,所以,最后输出ri来作为求得的水平面高度。

代码如下

#include <iostream>
#include <stdio.h>
#include <string>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
struct cistern{
    double b,h,w,d;
}a[50009];
int n,k;//k组数据,每组n个长方体
const double eps=1e-8;
int main(){
    double v;
    scanf("%d",&k);//cin>>k;
    while(k--){
        scanf("%d",&n); //cin>>n;
        double s=0,le=1000009,ri=0;
        for(int i=0;i<n;i++){
            scanf("%lf%lf%lf%lf",&a[i].b,&a[i].h,&a[i].w,&a[i].d); //cin>>a[i].b>>a[i].h>>a[i].w>>a[i].d;
            s+=a[i].h*a[i].w*a[i].d;
            le=min(le,a[i].b);//(le>a[i].b)?a[i].b:le;
            ri=max(ri,a[i].b+a[i].h);//(ri<(a[i].b+a[i].h))?(a[i].b+a[i].h):ri;
        }
        scanf("%lf",&v); //cin>>v;
        if(s+eps<v){
            puts("OVERFLOW");//cout<<"OVERFLOW"<<endl;
            continue;
        }
        while(le+eps<ri){
            double mid=(le+ri)/2.0;
            s=0;
            for(int i=0;i<n;i++){
                if(mid-a[i].b>=0){
                    if(mid-(a[i].b+a[i].h)>=0)
                        s+=a[i].d*a[i].h*a[i].w;
                    else
                        s+=a[i].d*a[i].w*(mid-a[i].b);
                }
            }
            if(s>=v)
                ri=mid;
            else
                le=mid;
        }
        printf("%.2lf\n",ri);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值