题目来源:POJ
地址:http://noi.openjudge.cn/ch0111/05/
-
总时间限制:
- 1000ms 内存限制:
- 65536kB
-
描述
-
我的生日要到了!根据习俗,我需要将一些派分给大家。我有N个不同口味、不同大小的派。有F个朋友会来参加我的派对,每个人会拿到一块派(必须一个派的一块,不能由几个派的小块拼成;可以是一整个派)。
我的朋友们都特别小气,如果有人拿到更大的一块,就会开始抱怨。因此所有人拿到的派是同样大小的(但不需要是同样形状的),虽然这样有些派会被浪费,但总比搞砸整个派对好。当然,我也要给自己留一块,而这一块也要和其他人的同样大小。
请问我们每个人拿到的派最大是多少?每个派都是一个高为1,半径不等的圆柱体。
输入
- 第一行包含两个正整数N和F,1 ≤ N, F ≤ 10 000,表示派的数量和朋友的数量。
- 第二行包含N个1到10000之间的整数,表示每个派的半径。
3 3 4 3 3样例输出
25.133
题目分析
- 利用二分查找寻求最大解。
- 利用函数确定所求最大姐是否满足条件
- 注意 pi的精准度
AC代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const double pi=3.141592653589;
const int maxn=10010;
int n,f,i;
int flag=0;
double sum=0;
double l,r,mid;
double a[maxn];
double v[maxn];
int result(double m,int f,int n,double v[]) {
int num=0;
for (int i=n-1; i>=0; i--) {
num+=(v[i]/m);
}
if (num<f) return 1;
else return 0;
}//result
void swap(double &x,double &y) {
double temp;
temp=x;
x=y;
y=temp;
return;
}//swap
int main() {
cin>>n>>f;
f++;
for(i=0; i<n; i++)
cin>>a[i];
for(i=0; i<n; i++) {
v[i]=pi*a[i]*a[i];
sum+=v[i]; //总体积 正确
}
sort(v,v+n); //快速排序
l=0;
r=v[n-1];
mid = l-(l-r)/2;
while (r-l>1e-5) {
if (result(mid,f,n,v)) {
r=mid;
mid=l-(l-r)/2;
} else {
l=mid;
mid=l-(l-r)/2;
}
}
printf("%.3f\n",l);
return 0;
}
备注
AC码修改自同学代码,部分多余没有删除。