7-5 派 (15 分)
我的生日要到了!根据习俗,我需要将一些派分给大家。我有N个不同口味、不同大小的派。有F个朋友会来参加我的派对,每个人会拿到一块派(必须一个派的一块,不能由几个派的小块拼成;可以是一整个派)。
我的朋友们都特别小气,如果有人拿到更大的一块,就会开始抱怨。因此所有人拿到的派是同样大小的(但不需要是同样形状的),虽然这样有些派会被浪费,但总比搞砸整个派对好。当然,我也要给自己留一块,而这一块也要和其他人的同样大小。
请问我们每个人拿到的派最大是多少?每个派都是一个高为1,半径不等的圆柱体。
输入格式:
第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示派的数量和朋友的数量。 第二行包含N个1到10000之间的整数,表示每个派的半径。
输出格式:
输出每个人能得到的最大的派的体积,精确到小数点后三位。
输入样例:
3 3
4 3 3结尾无空行
输出样例:
在这里给出相应的输出。例如:
25.133
结尾无空行
#include <iostream>
#include <math.h>
#define PI 3.1415926535898
using namespace std;
double volume(double r)
{
return PI * r * r;
}
int main()
{
int N; //派的数量
int F; //朋友的数量
cin >> N;
cin >> F;
double *pai = new double[N];
double r; //派的半径
double maxV = 0; //最大体积
//循环存入派的体积
for (int i = 0; i < N; i++)
{
cin >> r; //获取一个半径
pai[i] = volume(r); //计算派的体积并存入
if (pai[i] > maxV) //记录pai的最大值
{
maxV = pai[i];
}
}
//用类似极限的方法逼近那个可以满足的最大值
double left, right; //定义左右指针
double mid; //中值
left = 0;
right = maxV;
while (right - left > pow(10, -7))
{
mid = (left + right) / 2; //获得体积中值
int sum = 0; //记录每块饼能分出的最多块数
for (int i = 0; i < N; i++)
{
sum += (int)(pai[i] / mid);
}
if (sum > F) //当饼够人分时,说明可能还可以再分大一点 取体积区域的右半[mid,r]
{
left = mid;
}
else //当饼不够分时,说明划分区域太大了 取体积区域的左半[l,mid]
{
right = mid;
}
}
//当跳出循环时,说明已经处于能分的最大值
printf("%.3f", mid);
}