Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 10629 | Accepted: 3744 | Special Judge |
Description
Input
Output
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
Source
Northwestern Europe 2006
还是附上中文题目吧
13 派(NWERC 2006, LA 3635)
有F+1个人来分N个圆形派(半径不同),每个人得到的必须是一整块派,而不是几块拼在一起,且面积要相同。求每个人最多能得到多大面积的派(不必是圆形)。
【输入格式】
输入的第一行为数据组数T。每组数据的第一行为两个整数N和F(1≤N,F≤10 000);第二行为N个整数ri(1≤ri≤10 000),即各个派的半径。
【输出格式】
对于每组数据,输出每人得到的派的面积的最大值,精确到10-3。
思路:
显然二分答案 没什么好解释的了
附白书解释:
这个问题并不是“最小值最大”问题,但仍然可以采用二分答案方法,把问题转化为“是否可以让每人得到一块面积为x的派”。这样的转化相当于多了一个条件,然后求解目标变成了“看看这些条件是否相互矛盾”。
会有怎样的矛盾呢?只有一种矛盾:x太大,满足不了所有的F+1个人。这样,我们只需要算算一共可以切多少份面积为x的派,然后看看这个数目够不够F+1即可。因为派是不可以拼起来的,所以一个半径为r的派只能切出[πr2/x]个派(其他部分就浪费了),把所有圆形派能切出的份数加起来即可。代码如下。
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; const double PI=acos(-1); const int maxn=10000+5; int N,F,r; double radius[maxn]; double ans; double squre; bool ok(double area) { int sum = 0; for(int i = 1; i <= N; i++) sum += floor(radius[i] / area); return sum >= F; } int getans() { double i=0,j=squre,m; while(j-i>1e-6) { m=(j+i)/2; if(ok(m)) i=m; else j=m; } ans=i; return 0; } int main() { // freopen("a.in","r",stdin); // freopen("a.out","w",stdout); int T; scanf("%d",&T); while(T--) { squre=-1; scanf("%d%d",&N,&F); F++; for(int i=1;i<=N;i++) { scanf("%d",&r); radius[i]=r*r*PI; squre=max(squre,radius[i]); } getans(); printf("%.4lf\n",ans); } return 0; }