派(二分答案)
05:派
- 总时间限制:
- 1000ms
- 内存限制:
- 65536kB
- 描述
-
我的生日要到了!根据习俗,我需要将一些派分给大家。我有N个不同口味、不同大小的派。有F个朋友会来参加我的派对,每个人会拿到一块派(必须一个派的一块,不能由几个派的小块拼成;可以是一整个派)。
我的朋友们都特别小气,如果有人拿到更大的一块,就会开始抱怨。因此所有人拿到的派是同样大小的(但不需要是同样形状的),虽然这样有些派会被浪费,但总比搞砸整个派对好。当然,我也要给自己留一块,而这一块也要和其他人的同样大小。
请问我们每个人拿到的派最大是多少?每个派都是一个高为1,半径不等的圆柱体。 - 输入
- 第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示派的数量和朋友的数量。
第二行包含N个1到10000之间的整数,表示每个派的半径。 - 输出
- 输出每个人能得到的最大的派的体积,精确到小数点后三位。
- 样例输入
-
3 3 4 3 3
- 样例输出
-
25.133
【思路】刘汝佳蓝本上的题目
一开始我是没想到用二分答案,虽然这些题都是二分答案类型的,(当你做一道题目时,你不能正在学什么就往什么方面考虑,你要想,用什么方法为什么用这个方法)但是没有标志性的
最小值最大的问法。然后我看了看题解。。。。。。
介绍一下蓝本的思路:每个人分最多分所有派里面积最大的,要么无限小(这是答案范围);卡答案的条件就是能不能分得到,显然是用二分答案的
所以 二分答案的题目 比较直接的问法 最小值最大 一看就是二分答案了,但是比较隐形的问法 首先要看看有这么几个特点1 能确定答案范围 2有卡答案的条件
orz
【代码】1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<iomanip> 5 #include<cmath> 6 using namespace std; 7 const double pi=acos(-1.0);// acos(-1.0)就是求-1.0的反余弦,经计算,acos(-1.0) 的值就是圆周率 8 const int MAXX=100009; 9 double a[MAXX]; 10 bool ok(double); 11 int n,f; 12 int main() 13 { 14 int T; 15 double maxx=0; 16 scanf("%d",&T); 17 while(T--) 18 { 19 scanf("%d%d",&n,&f); 20 for(int i=0;i<n;i++) 21 { 22 int r; 23 scanf("%d",&r); 24 a[i]=pi*r*r;//每个派的面积 25 maxx=max(maxx,a[i]);//max函数里的变量类型相同 ,都是double 26 } 27 double l=0,r=maxx; 28 while(r-l>1e-5)//精确 二分答案的套路过程 29 { 30 double m=(l+r)/2; 31 if(ok(m))l=m;//扩大范围,看看每个人能不能分到更多 32 else 33 r=m; 34 } 35 printf("%.3lf",l);//printf格式化输出会自动四舍五入; 36 } 37 return 0; 38 } 39 bool ok(double s)//每人是否能分面积s的派 40 { 41 int sum=0; 42 for(int i=0;i<n;i++) 43 { 44 sum+=floor(a[i]/s);//向下取整,分不到s的浪费; 45 } 46 return sum>=f+1;//能否分到 47 }
-