題目描述
林克的蛋糕
描述
林克被造的紀念日快要到了。根據任天堂公司的慣例,每年到這個時間都會一些蛋糕分給林克的朋友。這些蛋糕有不同的口味,比如南瓜蛋糕、堅果蛋糕、西瓜蛋糕、胡蘿蔔蛋糕、水果蛋糕等等(有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;
}