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 }
时间并不会因为你的迷茫和迟疑而停留,就在你看这篇文章的同时,不知道有多少人在冥思苦想,在为算法废寝忘食,不知道有多少人在狂热地拍着代码,不知道又有多少提交一遍又一遍地刷新着OJ的status页面……
没有谁生来就是神牛,而千里之行,始于足下!