SCAU10690 分面包

10690 分面包

该题有题解

时间限制:1000MS  内存限制:65535K
提交次数:90 通过次数:29

题型: 编程题   语言: G++;GCC

 

Description

在大一的时候,XCC还在stu union打酱油~~~~和十三还有奶子他们去外面吃吃喝喝是常有的事。
大家都知道空腹喝酒是有害肚子滴,所以呢,要买一些面包来下酒。不过我们有个习惯,
就是所有的n个人,每个人分得的面包必须长度相等(长度相等的面包的量是一样的),
同时捏~给每个人分面包时,分得的小面包必须是来自同一块面包的,即不能把两个不同面包各切一部分下来凑合成一份面包来分。
现在一起来的有n个人,买了m个面包,求每人分得的最长面包长度。

 

输入格式

第一行是人数 n 和面包数目 m (3<= n <= 16 , 1 <= m <= 100),第二行 m 个数字表示 m 个面包的长度 L ,均为整数( 1 <= L <= 1000000)

 

输出格式

每人分得的最长面包长度,保留2位小数

 

输入样例

3  3
3  3  3

 

输出样例

3.00

 

提示

注意题目描述

 

来源

 scau_acm

 
题意:m个不同长度的面包分给n个人,每个人分得的面包长度相等,求最长每人能分多少。注意:面包不能是几块小面包拼成的面包,只能是整一块,或者由整一块分成的小面包。
解题思路:这道题要求用二分查找,其实思路很好想到,求每人最多能分多少,只要将这个最长能分的长度作为二分查找的值就OK了。对于每个二分查找的猜测值,只需要判断以这个值作为分面包的长度所分得的小面包数量是否大于人数(这句话有点绕,多看几遍吧orz,表达能力捉急),如果大于等于人数,说明分的小面包过多,也就是长度太小,就将左边界移到上一个猜测值,如果小于人数,说明分的小面包不够多,也就是长度过大,就将二分查找的右边界减小到上一个猜测值。


以下的小面包表示分后的面包orz
 
#include <iostream>
#include <cstdio>
using namespace std;


int main()
{
	int n,m,i;
	double max=0;
	double L[105];
	scanf("%d%d",&n,&m);
	for(i=0;i<m;i++){
		scanf("%lf",&L[i]);
		if(max<L[i]) max=L[i];
	}
	double l,r;
	l=max/n;//小面包的最小可能长度
	r=max;//小面包的最大可能长度
	int cnt=0;
	double mid=l+(r-l)/2;;
	while(r-l>0.001){ //二分查找最大能分的长度
		mid = l+(r-l)/2;  //这就相当于(i+r)/2,不过可以防止(l+r)过大溢出int的范围,虽然这里的l和r都是double,并不会溢出hhh(但这样写是好习惯的说)
		cnt=0; //cnt为该长度下能分得的小面包
		for(i=0;i<m;i++){//对每个面包都以给定长度分成小面包,看能分出几个
			cnt+=(int)(L[i]/mid);//向下取整
		}
		if(cnt>=n) l=mid;//面包太短
		else r=mid;//面包太长
	}
	printf("%.2lf",mid);
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值