poj3122-Pie(二分法+贪心思想)
一,题意:
有f+1个人(包括自己),n块披萨pie,给你每块pie的半径,要你公平的把尽可能多的pie分给每一个人
而且每个人得到的pie来自一个pie,不能拼凑,多余的边角丢掉。
二,思路:
1,输入,并找出最大体积的pie
2,二分法记录每一种情况的体积,及能分给几个人,
贪心的思想:
先取能分给n-1个人的最大体积,逐渐减少每份pie的体积
直到最接近n个人都能获得的pie的最大的体积
3, 输出。
三,步骤:
1,输入,max存储最大的pie体积
2,二分法:
i,退出条件max-min <= 1e-6;
由n-1个人体积慢慢减少,逐渐接近n个人的体积,
最后mid存储的pie体积即为每个人分得的最大体积。
ii,count记录pie能分的份数
iii, 如果份数 < 人数,减少每份pie的体积,即max = mid ; mid = (min+max)/2;
否则,增加每份pie的体积,即min = mid ; mid = (min+max)/2;
3,输出:注意控制输出的小数位数。
1 #include<iostream>
2 #include<iomanip>
3 using namespace std;
4 const double PI = 3.14159265359; //这是最短的PI长度,再短就WA了
5 const double esp = 1e-6; //为了double二分法设定的最小精度限制值
6 double pie[10050];
7
8 int main(){
9 int t , n , f; //n表示一开始pie的份数,f表示朋友的人数
10 cin>>t;
11 while(t--){
12 cin>>n>>f;
13 f++; //人数加上自己
14 double max = 0.0;
15 for(int i = 0 ; i < n ; i++){
16 cin>>pie[i];
17 pie[i] *= pie[i]; ////半径平方,计算pie的体积时先不乘PI,为了提高精度和减少时间
18 if(max<pie[i])
19 max = pie[i]; //记录最大pie的体积
20 }
21 double min = 0.0 ; //注意改为0,会出错
22 double mid ;
23 while(max-min>esp){ //实数double的二分结束条件不同于整数int的二分结束条件
24 mid = (min + max)/2;
25 int count = 0 ; //记录根据不同的mid尺寸能分多少份数
26 for(int i = 0 ; i < n ; i++){
27 count += (int)(pie[i]/mid);//第i个pie按照mid的尺寸去切,最多能分的人数(取整)
28 }
29 if(count < f) max = mid ; //mid偏大
30 else min = mid ; //mid偏小
31 // cout<<count<<"-"<<mid<<" "; //输出一下,你会发现其中的奥妙。
32 }
33 cout<<fixed<<setprecision(4)<<PI*mid<<endl;//fixed与setprecision配合使用规定小数点后的位数
34 }
35 return 0;
36 }
版权声明:本文为博主原创文章,未经博主允许不得转载。