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 }
View Code

版权声明:本文为博主原创文章,未经博主允许不得转载。

原文地址:https://www.cnblogs.com/My-Sunshine/p/4889512.html