题目描述
林克的蛋糕
描述
林克被造的纪念日快要到了。根据任天堂公司的惯例,每年到这个时间都会一些蛋糕分给林克的朋友。这些蛋糕有不同的口味,比如南瓜蛋糕、坚果蛋糕、西瓜蛋糕、胡萝卜蛋糕、水果蛋糕等等(有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;
}