题目大意:
我的生日马上就要到了,习惯上我会请大家吃馅饼,通常不止一块而是由很多块,饼都是圆柱形的,高度都为1,各饼的半径可以不同。
我将买N块馅饼,并且我将有F位朋友前来助兴(1 ≤ N, F ≤ 10,000),每人将得到一块饼(可能不完整),这块饼只能来自某块饼的一部分,每人只能有一块,不能超过一块,否则看上去将会很凌乱,还有就是我的朋友很在乎公平,每个人得到的饼的体积必须相同,还有就是我自己本人也要分的一块。
现有多个测例(测例数题中会给出),每个测例中都会给出N和F的值以及各个馅饼的半径(半径都为正整数,范围为[1, 10,000]),对于每个测例,求出每个人可分的的饼的最大体积,精度为10E-3,结果截断至4位小数。
注释代码:
/*
* Problem ID : POJ 3122 Pie
* Author : Lirx.t.Una
* Language : C
* Run Time : 32 ms
* Run Memory : 216 KB
*/
#include <stdio.h>
//π,AC的最低精度(测试过)
#define PI 3.14159265359
//精度上限取题中要求的平方(10E-3)
#define ESP 1E-6
//maximum number of people
//最大人数,包括自己
//为10,000 + 1
#define MAXPN 10001
//volume,各个馅饼的体积
//暂存R × R的值以保证精度
//最后输出结果的时候再乘上π
int v[MAXPN];
int
main() {
int t;//测例数
int n, f;//馅饼数和人数
int i;//计数变量
int max;//最大的馅饼的体积
//count,记录值
//若每人分得体积为mid时将所有馅饼用上可以分多少人
int cnt;
//在实数区间上进行二分,因此取double双精度值
//[lft, rht]表示人均分得体积的可能区间
//mid为区间中点
//就是在该区间上进行二分逼近结果
double lft, rht, mid;
scanf("%d", &t);
while ( t-- ) {
scanf("%d%d", &n, &f);
f++;
for ( max = 0, i = 0; i < n; i++ ) {
scanf("%d", v + i);
v[i] *= v[i];//先求R的平方以保证精度
//最后再乘上π
if ( v[i] > max )
max = v[i];
}
if ( 1 == n ) {//若只有一块饼则大家直接平分
//避免特殊情况下还有二分,节省时间
printf("%.4f\n", (double)max * PI / (double)f);
continue;
}
//假设答案可能的区间为[0.0, max]
lft = 0.0;
rht = (double)max;
while ( rht - lft > ESP ) {//由于浮点相减不能精确等于0
//因此要和一个极小小数进行比较,ESP即精度极限
mid = ( lft + rht ) / 2.0;
for ( cnt = 0, i = 0; i < n; i++ )//计算每个饼都用上能分给多少人
cnt += (int)( (double)v[i] / mid );
if ( cnt >= f )//人数够
lft = mid;//向更大探索
else//不够分,表示人均太大
rht = mid;//向更小探索
}
printf("%.4f\n", mid * PI);
}
return 0;
}
无注释代码:
#include <stdio.h>
#define PI 3.14159265359
#define ESP 1E-6
#define MAXPN 10001
int v[MAXPN];
int
main() {
int t;
int n, f;
int i;
int max;
int cnt;
double lft, rht, mid;
scanf("%d", &t);
while ( t-- ) {
scanf("%d%d", &n, &f);
f++;
for ( max = 0, i = 0; i < n; i++ ) {
scanf("%d", v + i);
v[i] *= v[i];
if ( v[i] > max )
max = v[i];
}
if ( 1 == n ) {
printf("%.4f\n", (double)max * PI / (double)f);
continue;
}
lft = 0.0;
rht = (double)max;
while ( rht - lft > ESP ) {
mid = ( lft + rht ) / 2.0;
for ( cnt = 0, i = 0; i < n; i++ )
cnt += (int)( (double)v[i] / mid );
if ( cnt >= f )
lft = mid;
else
rht = mid;
}
printf("%.4f\n", mid * PI);
}
return 0;
}
单词解释:
pie:n, 馅饼,饼图
come up:vi, 走近,发生
traditionally:adv, 传统上,习惯上
serve:vt, 供应,招待
messy:adj, 凌乱的,脏乱的
annoying:adj, 恼人的
complain:vt, 抱怨,发牢骚
spoil:vt, 糟蹋,溺爱
sylindrical:adj, 圆柱形的
radius:n, 半径
radii:n, 半径(复数形式)
absolute error:n, 绝对误差
volume:n, 体积