poj 3122

来源:互联网 发布:2017年各月m2数据 编辑:程序博客网 时间:2024/05/17 04:21

题目概述:

Special Judge!

有times组数据

每组有ps个蛋糕,分给fs+1个人,每个人分到的大小等大,但每个人分到的部分必须来自同一个蛋糕

蛋糕都是圆柱体,底面半径o(字母),高度1(数字)

输入:

第一行times,下一行ps,fs,下一行有ps个数,多组数据之间没有空行

限制:

1<=ps,fs,o<=10000,所有输入均为正整数

输出:

每行一个浮点数,每个人能分到的蛋糕的最大体积,与标准答案的误差不得大于0.001

样例输入:

3

3 3

4 3 3

1 24

5

10 5

1 4 2 3 4 5 6 5 4 2

样例输出:

25.1327

3.1416

50.2655

讨论:

这是额遇到的第一个special judge的题,百度一下才知道什么意思,样例输出给的是题目自带的,因为额的输出是保留默认6位小数,误差小于1e-5的,样例输出保留4位,误差小于1e-4,这个不影响最终结果和程序性能

原题中有一个小坑,需要仔细审题,即自己也要参与分配,因此fs需要加1

这个题看着似乎是个很复杂的算法,其实就是二分的思想,和猜价格游戏一样每次把范围缩小一半而已,而且再仔细看看,完全是个暴力解法,每次得到新数据就把整个数组遍历+判断一遍,并无新意,不过要理解到这一点似乎并不容易

同样也有一点贪心的思想,就是即便每个人都刚好能分到,也会把人均大小提高

题解状态:

268K,16MS,C++,1024B

#include<cmath>#include<cctype>#include<cstring>#include<algorithm>#include<cstdio>#include<numeric>#include<vector>#include<set>#include<map>#include<queue>#include<list>#include<stack>using namespace std;const double pi = 4 * atan(1.0);//精度较高的办法,有pi必用int ps, fs;//pies,friends,因为无论check函数还是fun函数都需要这两个参数,为方便而设为全局double pies[10005];//存放每个蛋糕的数据inline bool check(double a)//检查蛋糕分配状态的函数{int cnt = 0;for (int p = 0; p < ps; p++) {cnt += int(pies[p] / a);//既然只能在一个蛋糕里分,用这种方法可以比较简单直白的数出可以分出多少人份的}if (cnt < (fs + 1)) {return false;//每个人分的蛋糕太大,有人分不到} else {return true;//分的太小,可分配给的人数比总人数多,或者刚好每人都能分到,但是由于贪心,仍有可提高人均大小}}double fun(void){double total = 0;for (int p = 0; p < ps; p++) {int o;//这里用o纯属个人习惯:临时变量从键盘p往左取,以前为避免混淆也会跳过o,不过和0还是有些差别的scanf("%d", &o);//inputpies[p] = o*o;//注意这里存放的是每个蛋糕半径的平方,本打算用int数组,因类型转换不方便也就算了total += pies[p];求出所有蛋糕总大小,便于划定每个人蛋糕的最大值}double high = total / (fs + 1), low = 0.0, mid;//二分的思想,总感觉下界有优化的可能while (high - low > 1e-5) {mid = (high + low) / 2;if (check(mid)) {//仍可提高low = mid;} else {//需要减小high = mid;}}return mid*pi;//只有这一个地方用到pi}int main(void){//freopen("vs_cin.txt", "r", stdin);//freopen("vs_cout.txt", "w", stdout);int times;scanf("%d", &times);while (times--) {scanf("%d%d", &ps, &fs);//inputprintf("%lf\n", fun());//output}}

EOF

0 0