POJ 3122--Pie

20 篇文章 0 订阅

题意:把N个pie分给M个人,每人得到相同体积为V的一块,求最大的V。

  1. 设V[x]为分成x份时的最大体积,x = 1,2,...,M。易知V[x] >= V[x+1],上式的小于是肯定不存在的,因为少分一个人则V[x]至少等于V[x+1]。等于是可能存在的,例如把半径分别为4,3,3的3块饼分给2个或3个人的最大体积是一样的。
  2. 利用贪心方法:以V‘作为最大体积,将N个pie切分,最多能分成m份。易知,若m < M,则V[M] < V’。
  3. 由1,2得出二分:当m < M时,right = mid-precision;当m >= M时,left = mid。
需要注意的是,题目要求精度为1e-4,所以precision = 1e-5。另外3中的left = mid也需要改变,因为若全部pie的半径一样,显然最终结果为最初设置的上界,则二分会根据double的精度一步步将left加到超过right,会导致超时,所以我们可以在精度允许的情况下,同样每次将left加上1e-5。

#include<cstdio>
#define maxN 10005
#define precision 0.00001
#define pi  3.141592653589793238462643383279

int N,M;
double radii[maxN];

int calc_num(double v)
{
    int i;
    int num = 0;
    for(i = 0;i < N;i++)       //贪心计算体积为V时的最大份数
        num += radii[i]/v;
    return num;
}

int main()
{
    int T,i;
    char strIn[7];
    char c;
    int num;
    double left,mid,right;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&N,&M);
        M++;
        left = right = 0;
        getchar();
        for(i = 0;i < N;i++)
        {
            num = 0;
            while((c = getchar())&&(c != ' ')&&(c != '\n')&&(c > 0))  //读优化
            {
                num *= 10;
                num += c-'0';
            }
            radii[i] = num*num;
            if(left < radii[i])
                left = radii[i];
        }
        right = left;
        left /= M;
        while(left < right)
        {
            mid = (left+right)/2;
            if(calc_num(mid) < M)
                right = mid-precision;
            else
                left = mid+precision;   //此处不加精度会按照double的精度逼近则超时
        }
        printf("%.4f\n",left*pi);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值