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
解题思路:这道题要求用二分查找,其实思路很好想到,求每人最多能分多少,只要将这个最长能分的长度作为二分查找的值就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;
}