题意:把N个pie分给M个人,每人得到相同体积为V的一块,求最大的V。
- 设V[x]为分成x份时的最大体积,x = 1,2,...,M。易知V[x] >= V[x+1],上式的小于是肯定不存在的,因为少分一个人则V[x]至少等于V[x+1]。等于是可能存在的,例如把半径分别为4,3,3的3块饼分给2个或3个人的最大体积是一样的。
- 利用贪心方法:以V‘作为最大体积,将N个pie切分,最多能分成m份。易知,若m < M,则V[M] < V’。
- 由1,2得出二分:当m < M时,right = mid-precision;当m >= M时,left = mid。
需要注意的是,题目要求精度为1e-4,所以precision = 1e-5。另外3中的left = mid也需要改变,因为若全部pie的半径一样,显然最终结果为最初设置的上界,则二分会根据double的精度一步步将left加到超过right,会导致超时,所以我们可以在精度允许的情况下,同样每次将left加上1e-5。
#include<cstdio>
#define maxN 10005
#define precision 0.00001
#define pi 3.141592653589793238462643383279
int N,M;
double radii[maxN];
int calc_num(double v)
{
int i;
int num = 0;
for(i = 0;i < N;i++) //贪心计算体积为V时的最大份数
num += radii[i]/v;
return num;
}
int main()
{
int T,i;
char strIn[7];
char c;
int num;
double left,mid,right;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&N,&M);
M++;
left = right = 0;
getchar();
for(i = 0;i < N;i++)
{
num = 0;
while((c = getchar())&&(c != ' ')&&(c != '\n')&&(c > 0)) //读优化
{
num *= 10;
num += c-'0';
}
radii[i] = num*num;
if(left < radii[i])
left = radii[i];
}
right = left;
left /= M;
while(left < right)
{
mid = (left+right)/2;
if(calc_num(mid) < M)
right = mid-precision;
else
left = mid+precision; //此处不加精度会按照double的精度逼近则超时
}
printf("%.4f\n",left*pi);
}
return 0;
}