寒假每日一题剪绳子(个人练习)详细题解+推导证明(第六天)
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, 1≤N,M≤100000,
- 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打卡。
以上是关于寒假每日一题剪绳子(个人练习)详细题解+推导证明(第六天)的主要内容,如果未能解决你的问题,请参考以下文章
寒假每日一题找硬币(个人练习)详细题解+推导证明(第十二天)
寒假每日一题回文平方(个人练习)详细题解+推导证明(第五天)