链接:http://poj.org/problem?id=3122
题意:我要开个生日party,来了F个朋友。有几个不同大小,厚度一样的Pie要分给他们吃,当然我也要一份。
要求每个人分的的pie的面积是一样的,但是每个人只能有一块pie,而不是几块零碎的拼起来。所以,有可能会浪费一些Pie,这个没办法。
求每个人能分到的最大的Pie的面积。
二分求解,学到不少东西哈。详见代码。
#include<cstdio>
#include<cstring>
#include<cmath>
#define MAX 10010
#define PI 3.1415926535898
double r[MAX];
int main()
{
int test,n,f,ans,i;
double low,high,mid,max,temp,sum; //这里的low和high必须去double
scanf("%d",&test);
while(test--)
{
scanf("%d%d",&n,&f);
memset(r,0,sizeof(r));
max=0;
sum=0;
for(i=0;i<n;i++)
{
scanf("%lf",&r[i]);
sum+=(r[i]*r[i]);
//if(max<(r[i]*r[i]))
//max=(r[i]*r[i]);
}
//high=max; //上界:取所有pie中半径最大的,这个也能过
high=sum/(f+1);//但我在这里取的是所有半径的平方加起来除以所有人的为上界
//应该比上面那个要小些吧
low=0; //下界直接取row等于0,一开始还纠结了好久取多少,待了好几个都错。干脆就0吧
mid=0;
while(fabs(low-high)>(1e-6))//如果low和high是int,则这里的精度控制不会起到作用
{ //这样的二分其实也是第一次做,要学会用精度控制循环条件
//而不只是一味地low<=high
mid=(high+low)/2;
ans=0;
for(i=0;i<n;i++)
{
temp=r[i]*r[i];
temp/=mid; //每个人吃的面积是mid,一块pie最多能分的块数
ans+=temp;
}
if(ans<f+1)//如果ans<f+1,说明mid太大
high=mid;
if(ans>=f+1)//如果ans>=f+1,说明mid太小,因为求最大,所以要有等号
low=mid;//注意!!!这里mid直接赋值给low或者high,而不是加1或者减1再赋值
//因为这里的mid是double型的,而不是整数型,这个处理要注意啊
}
printf("%.4lf\n",mid*PI);
}
return 0;
}