POJ-3122.Pie(二分法最大化平均值)

  二分法的主题思路就是逐步逼近,所以这道题的思路自然一目了然,做题思路也是...

本题大意:题主过生日,它买了N块半径为R[ i ],高为1的圆柱形蛋糕,现在他要将这N块蛋糕等分给F + 1个人,为了好看分出来的每块蛋糕必须是从一整块上分割下来的,体积一样形状不限。

本题思路:那就是求那个最大的平均值啦,二分,找出最大值和最小值,二分逼近判断,就ok。

  这题卡精度的一批,double二分,老套路二分100次精度异常高,什么都不用管直接AC,我一开始也wa了几次,原因时因为check函数内部实现,我就把check里的除法向下取整改为了加法,就wa,不明白,懵懂无知,有大佬指点一下?

参考代码:

 1 #include <cstdio>
 2 #include <cmath>
 3 #include <algorithm>
 4 #define mid ((double)(l + r) / 2)
 5 using namespace std;
 6 
 7 const double pi = acos(-1.0);
 8 const int maxn = 10000 + 5; 
 9 int N, F;
10 int R[maxn];
11 double V[maxn];
12 
13 bool cmp(const double &a, const double &b) {
14     return a > b;
15 }
16 
17 double Getarea(int r) {
18     return (double)(pi * r * r);
19 }
20 
21 // bool check(double x) {
22 //     int num = 0;
23 //     for(int i = 0; i < N; i ++) {
24 //         double cap = V[i];
25 //         while(cap >= x) {
26 //             num ++;
27 //             cap -= x;
28 //         }
29 //         if(num >= F + 1) return true;
30 //     }
31 //     return num >= F + 1;
32 // }
33 
34 bool check(double x) {
35     int sum = 0;
36     for(int i = 0; i < N; i ++)
37         sum += (int)(V[i] / x);
38     return sum >= F + 1;
39 }
40 
41 int main() {
42     int t;
43     double Max = 0;
44     scanf("%d", &t);
45     while(t --) {
46         scanf("%d %d", &N, &F);
47         for(int i = 0; i < N; i ++) {
48             scanf("%d", &R[i]);
49             V[i] = Getarea(R[i]);
50             Max = max(Max, V[i]);
51         }
52         double l = 0, r = double(Max);
53         for(int i = 0; i < 100; i ++) {
54             if(check(mid)) l = mid;
55             else r = mid;
56         }
57         printf("%.4f\n", l);
58     }
59     return 0;
60 }

 

posted @ 2019-05-24 23:56  Cruel_King  阅读(212)  评论(0编辑  收藏  举报