AcWing 680. 剪绳子(寒假每日一题)入门组

题目描述
有N根绳子,第i根绳子长度为Li,现在需要M根等长的绳子,你可以对N根绳子进行任意裁剪(不能拼接),请你帮忙计算出这M根绳子最长的长度是多少。

输入格式
第一行包含2个正整数N、M,表示原始绳子的数量和需求绳子的数量。

第二行包含N个整数,其中第 i 个整数Li表示第 i 根绳子的长度。

输出格式
输出一个数字,表示裁剪后最长的长度,保留两位小数。

数据范围
1≤N,M≤100000,
0<Li<109

输入样例:

3 4
3 5 4

输出样例:

2.50

样例解释
第一根和第三根分别裁剪出一根2.50长度的绳子,第二根剪成2根2.50长度的绳子,刚好4根。

思路:
看题解之前,看到这道题感觉跟昨天刷的分巧克力题目很相似

分巧克力思路:直接求长度不好求,但是如果给我们一个长度让我们求用这个长度可以切多少条绳子是较为简单的(最优化→判定问题)

应该可以用二分来做,但是唯一不同的是这个是实数,巧克力那道题是整数,浮点数二分非常好写,男的是整数,需要考虑边界问题。
在这里插入图片描述
AC代码

#include <iostream>
#include <algorithm>
#include <cstring>

using namespace std;

const int N = 100010;

int n, m;
int h[N];

bool check(double mid){
    
    
    int res = 0;
    for(int i = 0; i < n; i ++){
    
    
        res += h[i]/mid;
        if(res >= m) return true;
    }
    return false;
}

int main()
{
    
    
    cin >> n >> m;
    for(int i = 0; i < n; i ++) cin >> h[i];

    double l = 0, r = 1e9;//二分初始左右边界
    while(r - l > 1e-4){
    
    //???
        double mid = (l + r)/2;//浮点数二分不需要考虑溢出
        if(check(mid)) l = mid;
        else r = mid;//浮点数不需要考虑下取整(mid-1)上取整(mid+1)等情况
    }
    printf("%.2lf\n", r);//l=r

    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43232564/article/details/113767221