题目链接:POJ 3122 Pie(二分枚举)
题没读懂,求了个平均值QAQ
【题意】
大致题意为就是公平地分披萨pie,有n个pie,找来f个朋友,加上自己那么总人数共 f+1人(注意)。每个pie都是高为1的圆柱体,输入这n个pie的半径,如果要公平地把pie分给每一个人(就是所有人得到的pie尺寸一致,但是形状可以不同),而且每个人得到的那份pie必须是从同一个pie上得到的(注意这个陷阱)。
就是说如果有3个pie, 尺寸分别为1,2,3,如果要给每人尺寸为2的pie,那么最多分给2个人,而不是3个人因为第一个pie尺寸为1,小于2,应该被扔掉。第二个pie尺寸为2,等于2,刚好分给一个人。第三个pie尺寸为3,切出尺寸为2的一份,分给一个人,剩下的尺寸为1的就扔掉千万不要陷入 (1+2+3)/2=3人的误区,这样就变成求平均了(注意)这是一个二分法的题目,我们不断进行二分演算就可以了,还要注意的就是精度的问题。
【解题思路】
设每人最多能得到的派为 x,首先可以确定 x 不会超过最大的一块派,所以x的上限就为max(派i),进入二分查找最大的x,二分思路如下:如果可以按照x分,尝试下更大的(low=mid);如果不能,就尝试小一些的(high=mid)。
#include<iostream>
#include<algorithm>
#include<string>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
const int MOD = 10000007;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1.0);
const double eps = 1e-6; //根据题目要求设置精度,第一次的1e-8超时了
const int maxn = 10010;
double v[maxn]; //体积
int n,f;
bool check(double x)
{
int cnt = 0;
for(int i=0;i<n;i++)
{
cnt += (int)(v[i]/x);
if(cnt>=f+1) //注意f+1个人
return true;
}
return false;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%d",&n,&f);
double maxsize = 0; //寻找最大尺寸作为二分上界
for(int i=0;i<n;i++)
{
scanf("%lf",&v[i]); //输入半径
v[i] = v[i]*v[i]*PI; //体积
if(v[i]>maxsize)
maxsize = v[i];
}
double l = 0; //二分下界
double r = maxsize; //二分上界
double mid;
while(r-l>eps) //浮点数比较与整数不同,注意精度的选择
{
mid = (r+l)/2;
if(check(mid))
l = mid;
else
r = mid;
}
printf("%.4f\n",mid);
}
return 0;
}
在POJ上交代码时,最后的输出只能是%.4f 不能是%.4lf。