寒假每日一题剪绳子(个人练习)详细题解+推导证明(第六天)

Posted 我是管小亮

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寒假每日一题剪绳子(个人练习)详细题解+推导证明(第六天)相关的知识,希望对你有一定的参考价值。

文章目录

前言

今天终于出核酸检测的结果,还好大家都没事,不然怕是要封城了!!!

今天还是寒假每日一题,不是软广,不是硬广,只是个人练习,题目来自今日头条2019,笔试题。

我发现二分法真的是个神奇的算法,厉害的人万物皆可二分,虚心学习一下。

题目

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

输入格式

  • 第一行包含2个正整数N、M,表示原始绳子的数量和需求绳子的数量。
  • 第二行包含N个整数,其中第 i 个整数Li表示第 i 根绳子的长度。

输出格式

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

数据范围

  • 1 ≤ N , M ≤ 100000 , 1≤N,M≤100000, 1N,M100000,
  • 0 < L i < 109 0<Li<109 0<Li<109
输入样例:
3 4
3 5 4

输出样例:
2.50

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

详细题解

写法1 O ( n l o g n ) O(nlogn) O(nlogn)

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

using namespace std;

const int N = 100005;

int n, m;
int f[N];

bool check(double mid)

    int cnt = 0;
    for (int i = 0; i < n; ++ i )
    
        cnt += f[i] / mid;
    
    return cnt >= m;


int main()

    cin >> n >> m;
    for (int i = 0; i < n; ++ i ) cin >> f[i];
    
    double left = 0, right = 1e9;
    while (right - left > 1e-4)
    
        double mid = (left + right) / 2;
        if (check(mid)) left = mid;
        else right = mid;
    
    printf("%.2lf", right);
    
    return 0;

毫无疑问个锤子,我真的是服气了这个题,通过增加一个额外的条件,把最优化问题转换成判定问题,o( ̄▽ ̄)d

现在来好好复盘一下这个题目。

首先题目很多人读蒙了,其实就是给你 n 多条绳子,和需要 m 条绳子,让你求一个最后裁剪完的绳子的最大值,具体以实例来说。

输入样例:
3 4
3 5 4

输出样例:
2.50

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

现在一共是 3 条绳子,分别是3 5 4,最后需要 4 条绳子,所以你需要对 3 条绳子进行裁剪。那么怎么才能让这 4 条绳子的长度和最大呢?自然是在满足绳子数量为 4 的前提下,让每一条绳子最长。

比如,

  • 如果让每一条绳子都是 1 的话,肯定是可以满足 4 条绳子的概念的,但是 1 * 4 = 4,这就看起来很小了;
  • 如果让每一条绳子都是 2 的话,第一条绳子 3 可以裁剪出一个 2 来,第二条绳子 5 可以裁剪出 2 个 2 来,第三条绳子 4 也能裁剪出一个 2 来,这样就是4条绳子了,综合 2 * 4 = 8,肯定是比 4 要大的。
  • 以此类推,所以这是一个浮点数量级的题目。

那么如何转换成二分法呢?

现在给定每一条绳子的最大值和最小值,那么裁剪之后的绳子长度一定在这两个值之间,但是这个绳子的长度是如何限制的呢?没错,就是需求的绳子数量 m,所以通过遍历 n 条绳子,让每一条绳子对长度 mid 进行向下取整,即可得到所有绳子中能裁剪成 mid 长度的绳子数量,如果这个数量是大于或者等于 m 的,那么说明 mid 是可以的,甚至可以更大,否则就是需要更小。

最后提交,AC😁

推导证明

其实转换成二分法之后,这个题目就已经完成了,来画个图简单分析一下。


这里我例举了四种情况,分别是两种小的时候,一种大的时候,还有一种最优解的时候。

可以看出,

  • 如果长度设置太小,那么就会导致最终长度和太小,同时数量可能会偏大;
  • 如果长度设置太大,那么就会导致数量不符合;
  • 只有长度正正好,才能在保持数量符合的前提下,让最终长度和最大。

举一反三

浮点数二分法

总结

继续努力,坚持更新,重新翻看《雪中悍刀行》,还是会被李淳罡的风采折服,6th打卡。

开发者涨薪指南 48位大咖的思考法则、工作方式、逻辑体系

以上是关于寒假每日一题剪绳子(个人练习)详细题解+推导证明(第六天)的主要内容,如果未能解决你的问题,请参考以下文章

寒假每日一题找硬币(个人练习)详细题解+推导证明(第十二天)

寒假每日一题回文平方(个人练习)详细题解+推导证明(第五天)

寒假每日一题红与黑(个人练习)详细题解+推导证明(第四天)

寒假每日一题数字三角形(个人练习)详细题解+推导证明(第二天)

寒假每日一题奖学金(个人练习)详细题解+推导证明(第十天)

寒假每日一题翻硬币(个人练习)详细题解+推导证明(第十一天)