二分查找—林克的蛋糕

题目描述


林克的蛋糕
描述

林克被造的纪念日快要到了。根据任天堂公司的惯例,每年到这个时间都会一些蛋糕分给林克的朋友。这些蛋糕有不同的口味,比如南瓜蛋糕、坚果蛋糕、西瓜蛋糕、胡萝卜蛋糕、水果蛋糕等等(有N种不同口味,大小不同的蛋糕)。
为了公平,每个朋友都会分到一块大小相同的蛋糕(不需要同样形状,但是要同一种口味,不允许混合口味,否则就会变成奇怪的菜肴)。
假设每个蛋糕都是一个高为1,半径不等的圆柱体,一共有F+1个人(F是林克的朋友个数,还要加上林克的设计者)。

所有人拿到的蛋糕是同样大小的,请问每个人拿到的蛋糕最大是多少?

输入
第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示蛋糕的数量和朋友的数量。

第二行包含N个1到10000之间的整数,表示每个蛋糕的半径。

输出
输出每个人能得到的最大的蛋糕的体积,精确到小数点后三位。

输入样例 1

3 3
4 3 3
输出样例 1

25.133

思考过程


每个蛋糕只有一种,V固定
总共friend个人,每个人只能有一种

找到最大的蛋糕,有一定用处?

每个人的最大蛋糕,最大只能是所有体积之和 / friend (上界)
下界我们直接设为0

想不到什么好的数学办法

直接暴力二分-分发?!!!
from 0 to max
如何确定分配是否正确?
从大到小依次整除(一个 double 的temp v)
最后加起来是否大于friend
那么现在只要确定边界!(精确问题需要考虑)
依旧记录left,循环条件是??
算到right

代码

#include<iostream>
#include<cmath>
#include<algorithm>
const double PI= acos(-1.0);//cos(PI)=-1; 精度需要准确
using namespace std;
int N,Friend;
double v[10010];
bool canDistributed(double size,int people)
{   
    //每一个蛋糕V依次除以size ++;
    int num=0;
    for(int i=0;i<N;i++)
    {
        int temp=v[i]/size;
        num+=temp;
        if(num>=people)
        return true;
    }
     return false;
}
double binarySearch(double *nums,int n)
{
    //上边界的设置错误??? !!!!一开始这里错了,应该是总V 除以 总人数
    //count the sum
    double right=0,left=0;
    for(int i=0;i<n;i++)//所有蛋糕总体积 除以 friend 是每个人可以分到的最大的蛋糕大小
    	right+=nums[i];
    right/=Friend;
    while (right-left>1e-6)
    {
        double mid= left + (right-left)/2;
        if(canDistributed(mid,Friend))
            left=mid;
        else {
            right=mid;
        }
    }
    return left;
    
}
int main()
{
    int r;
    cin>>N>>Friend;
    Friend++;
    for(int i=0;i<N;i++)
    {
        cin>>r;
        v[i]=r*r;
    }
    printf("%.3lf",PI*binarySearch(v,N));
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章