poj3122

题目不难,就是题目不好理解,大致题意为:我过生日,做了N个蛋糕,形状为圆柱形,高度均为1,但是半径不一样。邀请f个朋友过生日。加上自己一共f+1人。要求每个人都有一个pie,并且每个人的pie的体积相同。同时,要求每个人的pie必须要从原有的一块pie上切割(或直接就是原有的一整块pie),题目要 求出 每个人可分得的最大体积的pie.

这个题目的难点就是读题和精度问题。首先要读懂:要求每个人的pie必须要从原有的一块pie上切割(或直接就是原有的一整块pie)。

如果这个读懂了,那么题目就水了。因为很明显的二分查找法求解单调函数。

思路如下:

假设num(V)表示:每个人可得pie体积为V,且此时最多有num(V)个人可分得该体积的pie。那么num(V)显然为单调递减函数(非严格单调函数)

那么接下来要确定的就是V的上下限,不妨设V的下限为所有体积的pie中的最小值,V的上限为所有体积的pie中的最大值,为了程序编写的方便,这里将下限设为0.0,上限设为

2.0*max(v)+1.0。那么我们就是要求得最大的满足条件: num(V)>=f+1的V.

下面是程序: 184K+47MS

#include <stdio.h>
#include <stdlib.h>
#define Max 10010
#define PI 3.14159265359 //PI的精度要经可能的高,经验
#define eps 1e-5 //最小距离
int r[Max];
int Case,n,f;
int main(){
	scanf("%d",&Case);
	while(Case--){
		scanf("%d%d",&n,&f);
		int tL=Max,tR=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&r[i]);
			if(r[i]<tL) tL=r[i];
			if(r[i]>tR) tR=r[i]; //最大半径
		}
		double left=0.0,right=2.0*tR*tR*PI+1.0,mid; // 下限为0,上限为2.0*tR*tR*PI+1.0
		while(right-left>eps){ // while条件
			mid=(right+left)/2.0;
			int num=0;
			for(int i=1;i<=n;i++){ // 求体积为mid时,可以分得的最多人数
				double temp=PI*r[i]*r[i];
				while(temp>=mid){ // 连续减法,直至不够减,将剩余的pie丢弃
					temp-=mid;
					num++; // 每减一次,人数增加一个
				}
			}
			if(num>=f+1) // 若最大人数大于或等于f+1时。则说明足够分,求最大值
				left=mid+0.00001;
			else  // 否则不够分,mid要减小
				right=mid-0.00001;
		}
		printf("%.4lf\n",right); // 小数点后保留4为输出。注意为right,而不为mid或left。
	}
	return 0;
}


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值