解题思路
可以利用二分查找的思想,假设一个面积值进行判断,如果成立则增大此面积再进行判断,不成立则减小面积,直到找到能成立的最大面积值输出。详细过程讲解看代码段。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const double pi=3.141592653589793;
const double EPS=1e-6;
int maxPai(double mid); //用于计算最大的派
void changepai(); //将输入的半径 r 改为 r^2
int n,f;
double pai[10000];
int main()
{
double max;
cin>>n>>f;
for(int i=0;i<n;i++)
{
cin>>pai[i];
}
changepai();
sort(pai,pai+n);
double l=0,r=pai[n-1],mid; //因为将数组排序,最大可以取的半径为最后一个
while(fabs(r-l)>EPS){
mid=l+(r-l)/2;
if(maxPai(mid)){ //成立时继续查找是否有更大的值
l=mid;
}
else r=mid; //不成立减小面积值
}
printf("%.3f",mid*pi);
}
int maxPai(double mid)
{
double paimax[10000];
memcpy(paimax,pai,sizeof(pai)); //将数组pai复制到paimax中
int peple=0;
for(int i=n-1;i>=0;i--)
{
while(paimax[i]>=mid) //该饼在此面积值下最多能给几个人分
{
paimax[i]-=mid;
peple++;
}
if(peple>=f+1) return 1; //当peple大于等于总人数时代表此mid面积值成立
}
return 0; //如果出了for循环则说明peple值始终没有大于总人数也就是此面积值太大了
}
void changepai()
{
for(int i=0;i<n;i++)
{
pai[i]*=pai[i];
}
}