[POJ 3122] Pie 二分答案+贪心

题目传送门:【POJ 3122】

题目大意:我和朋友们在生日宴会上分享蛋黄派,我们每个人都需要得到相同大小的派,并且每个人只能从一个完整的派上面切下一定大小的派(可以是完整的一块,也可以是切下来的一小块,不过不能由数个切下来的派拼凑而成)。求符合条件时,我们能得到派的面积的最大值。

输入一共有 T 组数据,每组数据的第一行为一个 N 和 F,代表 N 份派和 F 个朋友 (即:一共有 F+1 个人,包含自己);接下来的一行有 N 个数,代表每个派的半径。
输出则为每组数据对应的最大面积,答案的误差最多在 10^-3 之内。

题目分析:
一道比较入门的二分答案题。
由题,每个人最多能得到一个完整派,并且每个派都是等大的;最少则什么也得不到。因此,我们可以对此进行二分。
取 mid 为每个人能获得的最大面积与最小面积的中间值,如果当前的 mid 能使多于 F 个人得到这么大的派,说明每个人可能还会得到更大面积的派,那么往上查找;否则,当 mid 不能的时候,每个人得不到这么大面积的派,就往下查找。最终,我们就可以确定每个人得到的派面积的大小。可以证明这样做是正确的。

下面附上代码:

/* Author:ArcCCcp MEM:284KB TIME:63MS 未加优化*/

#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int MX=10005;
const double PI=3.1415926535897932;
const double ME=1e-5;        //二分查找的最小范围,小于这个范围的查找就显得没有必要

int n,f;
double size[MX];             //每个派的大小

int main(){
    int T;
    cin>>T;
    while (T--){
        memset(size,0,sizeof(size));
        cin>>n>>f;
        f++;                                       //包括自己
        double low=0.0,high=0.0;
        for (int i=1;i<=n;i++){
            cin>>size[i];
            size[i]*=size[i];

    //这里我们不选择乘上π的值,而是先保存半径的平方,避免浮点运算精度误差过大

            if (high < size[i]) high=size[i];
        }
        double mid=(high+low)/2.0;

        while (high-low > ESP){                    //二分答案
            int tot=0;
            mid=(high+low)/2.0;
            for (int i=1;i<=n;i++){
                tot+=(int)(size[i]/mid);
            }
            if (tot < f) high=mid;
            else low=mid;

    //如果分到当前大小的派的人达到了f,则说明可能还有分的更大的方法,往上查找;
    //如果没有达到f,那么当前面积太大,往下查找;

        }
        printf("%0.4lf\n",mid*PI);
    }
    return 0;
}
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值