UVa - 815 Flooded! 洪水 二分猜答案+排序 重庆一中高2018级竞赛班第三次测试 2016.7.24 Problem 1

【问题描述】
有一个n行m列的网格,每个格子是边长为10米的正方形,网格四周是无限高的墙壁,第i行第j列每个格子的海拔高度为h[i][j]。现在网格中有T立方米的水,请你计算网格中的水平面的海拔高度,以及有水格子数目。注意,在网格中,所有有水格子的水平面的海拔高度相同,所以有水格子的数量为海拔高度严格小于水平面高度的格子数目。

【输入格式】
第一行整数n和m,表示网格有n行m列。
接下来是n行m列的矩阵,第i行第j列的数字为对应格子的海拔高度h[i][j]。
最后一行为整数T,表示网格中水的体积。

【输出格式】
第一行为一个实数,表示水平面的海拔高度,保留2位小数。
第二行为一个整数,表示有水格子的数目。

【输入样例】

3 3
25 37 45
51 12 34
94 83 27
10000 

【输出样例】

46.67
6

【数据范围】
1<=n,m<=30
0<=h[i][j]<=1,000,000
1<=T<=1,000,000,000

:该题取自学校OJ,与原题的多组数据输入有区别。

思路:本来想用贪心算法做,但是感觉有些复杂,然后看到数据是double类型的,而且二分猜答案的结果可以很简单check,因此用二分猜答案完成。
先猜一个值,然后验证这个值计算出来的水的体积与T比较,若小于则可以往右边猜,若大于则往左边猜。

/*
    Name: flood.cpp
    Copyright: Twitter & Instagram @stevebieberjr
    Author: @stevebieberjr
    Date: 25-07-16 10:02
*/
#include<cstdio>
#include<algorithm>
using namespace std;

int n,m;
double T,h[35*35];

//二分猜答案

int check(double p)
{
    double sum=0;
    int i;
    for(i=1;i<=n*m;i++) //遍历每个点
    {
        if(h[i]<p) sum+=(p-h[i])*100; //高度小于猜的水平面高度,计算水的体积
        if(sum>T) //若水的体积已经超过T,break
        {
            break;
        }
    }
    if(i<n*m || sum>T) return 0; //sum>T的判断考试没有写错了一组数据,多一些判断总是好的
    return 1;
}

int main()
{
    freopen("flood.in","r",stdin);
    freopen("flood.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n*m;i++)
    {
        scanf("%lf",&h[i]);
    }
    scanf("%lf",&T);
    sort(h+1,h+1+(n*m)); //海拔从小到大排序

    double mid=0,A=0,B=2000000000;
    while(A<=B) //猜答案
    {
        mid=(A+B)/2.0;
        if(check(mid)) A=mid+0.00000001;
        else B=mid-0.00000001;
    }
    printf("%.2lf\n",A);
    int ans=0; //计算有水格子的数目,也可在猜答案时计算
    for(int i=1;i<=n*m;i++)
    {
        if(h[i]<A) ans++;
    }
    printf("%d\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值