二分查找—林克的蛋糕

題目描述


林克的蛋糕
描述

林克被造的紀念日快要到了。根據任天堂公司的慣例,每年到這個時間都會一些蛋糕分給林克的朋友。這些蛋糕有不同的口味,比如南瓜蛋糕、堅果蛋糕、西瓜蛋糕、胡蘿蔔蛋糕、水果蛋糕等等(有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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章