题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1969
题意:
多组案例。办生日Party,有N个馅饼,有F个朋友,接下来是N个馅饼的半径。然后是分馅饼,注意每个人都要一样大,形状没什么要求,但都要是一整块的,也就是说不能从两个饼中割一小块来凑一块。饼的厚度一致可看为1,所以面积和体积相等。打比方说,面积为10的和6的两块饼,如果每人分到面积为5,则10分两块,6切成5,够分3个人,如果每人6,则只能分2个了!题目要求每人分到的饼尽可能的大!
案例:
Sample Input
3
3 3
4 3 3
1 24
5
10 5
1 4 2 3 4 5 6 5 4 2
Sample Output
25.1327
3.1416
50.2655
分析:
该题跟我刚完成的抄书问题类似,均采用二分法查找。所需注意的是精度的设定,left和right要尽可能靠近,我初始将精度设定为十的负八次方,可惜的是超时,后改为负六次方才通过。还有要注意的是分蛋糕的人应包括自己在内,即有F+1个人分蛋糕,而且蛋糕切的块数许多不许少,要让每人分到的蛋糕面积尽可能大,就尽量避免浪费,蛋糕切分块数尽可能靠近要分的人数。另外,pi 用反余弦求出,精度更高。
源代码:
1 #include<cstdio> 2 #include<cmath> 3 int T,N,F; 4 double a[10005],r,left,right,mid; 5 double pi=acos(-1.0);//pi值确定 6 bool check(double max) 7 { 8 int j,tot=0; 9 for(j=1;j<=N;j++) 10 tot+=int(a[j]/max);//每人分max面积的蛋糕,计算所有蛋糕能分总数 11 if(tot>=F+1)//判断能否每人一块,许多不许少 12 return true; 13 else 14 return false; 15 } 16 int main() 17 { 18 int i; 19 scanf("%d",&T);//案例数 20 while(T--) 21 { 22 scanf("%d%d",&N,&F);//蛋糕数N和人数F 23 for(i=1;i<=N;i++) 24 { 25 scanf("%lf",&r);//单块蛋糕半径 26 a[i]=pi*r*r;//单块蛋糕面积 27 right+=a[i];//计算所有蛋糕总面积 28 } 29 left=0.0;//分配蛋糕最小面积极限 30 right=right/(F+1);//分配蛋糕最大面积极限 31 while((right-left)>1e-6)//二分法精度判定 32 { 33 mid=(left+right)/2.0; 34 if(check(mid)) 35 left=mid; 36 else right=mid; 37 } 38 printf("%.4lf ",mid);//最终结果 39 } 40 return 0; 41 }