【二分+贪心】用 N 根绳子裁剪出 M 根等长绳子

2023-10-31

有 N 根绳子,第 i 根绳子的长度为 l[i],现在需要 M 根等长的绳子。
你可以对这 N 根绳子进行任意裁剪(不能拼接),请你计算出这 M 根绳子最长的长度。
输入描述:
  第一行包括两个整数 N, M,含义如题所述(1 <= N, M <= 100000)
  第二行包含N个整数,分别对应N根绳子的长度(0 < l[i] < 109)
输出描述:
  一个数字,表示裁剪后最长的长度,保留两位小数

示例输入:
3 4
3 5 4
示例输出:2.50
解释: 第一根和第三根绳子分别裁剪出一根 2.50 长的绳子,第二根绳子刚好可以裁剪出两根 2.50 的长绳子,共 4 根。

  这道题其实就是问裁剪出 M 段等长绳子,最大裁剪长度是多少。像这样的 "找到一个数,它要满足一定条件" 的题目,第一反应就是 贪心+二分,比如 “公路建设加油站,使最小距离最大化” 这道题以及现在这道题。这道题就是找到一个长度值 X,使得 X 满足能够从已有的 N 根绳子中裁剪出来 M 段
  思路明确了,代码就比较好写了,注意因为不是整数的 l 和 r,所以判断条件从 r &gt; = l r &gt;= l r>=l 变成 r − l &gt; e p s r - l &gt; eps rl>eps,eps是一个自己设的数,比如 1e-6:

#include <iostream>
#include <vector>
using namespace std;

bool check_len(double len, const vector<int>& ropes, int target) {
	int cnt = 0;
	for(const int& r : ropes) {
		cnt += r / len;
		if (cnt >= target) return true;
	}
	return false;
}

int main() {
	int n, m, total_len = 0;
	cin >> n >> m;
	vector<int> ropes(n);
	for (int i = 0; i < n; ++i) {
		cin >> ropes[i];
		total_len += ropes[i];
	}
	double l = 0, r = total_len;
	while(r - l > 1e-6) {
		const double mid = l + (r - l) / 2.0;
		printf("l = %lf, r = %lf, mid = %lf\n", l, r, mid);
		if (check_len(mid, ropes, m)) l = mid;
		else                          r = mid;
	}
	printf("%.2f\n", r);
	return 0;
}

  运行结果如下:

3 4
3 5 4
l = 0.000000, r = 12.000000, mid = 6.000000
l = 0.000000, r = 6.000000, mid = 3.000000
l = 0.000000, r = 3.000000, mid = 1.500000
l = 1.500000, r = 3.000000, mid = 2.250000
l = 2.250000, r = 3.000000, mid = 2.625000
l = 2.250000, r = 2.625000, mid = 2.437500
l = 2.437500, r = 2.625000, mid = 2.531250
l = 2.437500, r = 2.531250, mid = 2.484375
l = 2.484375, r = 2.531250, mid = 2.507813
l = 2.484375, r = 2.507813, mid = 2.496094
l = 2.496094, r = 2.507813, mid = 2.501953
l = 2.496094, r = 2.501953, mid = 2.499023
l = 2.499023, r = 2.501953, mid = 2.500488
l = 2.499023, r = 2.500488, mid = 2.499756
l = 2.499756, r = 2.500488, mid = 2.500122
l = 2.499756, r = 2.500122, mid = 2.499939
l = 2.499939, r = 2.500122, mid = 2.500031
l = 2.499939, r = 2.500031, mid = 2.499985
l = 2.499985, r = 2.500031, mid = 2.500008
l = 2.499985, r = 2.500008, mid = 2.499996
l = 2.499996, r = 2.500008, mid = 2.500002
l = 2.499996, r = 2.500002, mid = 2.499999
l = 2.499999, r = 2.500002, mid = 2.500000
l = 2.499999, r = 2.500000, mid = 2.500000
2.50

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【二分+贪心】用 N 根绳子裁剪出 M 根等长绳子 的相关文章

  • Best Binary String

    Best Binary String 题意 给一个包含0 1 的字符串 可以换成0或1 要求换完之后使得成本最小 二进制字符串的成本定义为按非降序对字符串进行排序所需的 反转字符串的任意连续子字符串 形式的最小操作数 思路 因为每次操作是反
  • POJ--2709:Painter (贪心)

    1 题目源地址 http poj org problem id 2709 2 解题思路 每个颜料盒可能有3 12种颜色 其中每种颜色50ml 任意三种颜色 假设每种颜色Xml 可以混合出Xml的灰色 现在给出所需颜色的种数N 给出N个值分别
  • P1016 旅行家的预算【模拟+贪心】【详解】

    题目链接 思路 这道题是一道很明显的模拟题 但这道题也需要自己的理解 我自己写了些样例 然后找到了其中的模拟 我们假设从一个点出发 对于它的下一个点我们有很多选择 期间定义一个len用以记录满油 单次最远 到达距离 我们造访这条路上的所有点
  • 【NOIP 2004 提高组】合并果子

    题就自己找啦 各大OJ上应该都有 题目 题目描述 在一个果园里 多多已经将所有的果子打了下来 而且按果子的不同种类分成了不同的堆 多多决定把所有的果子合成一堆 每一次合并 多多可以把两堆果子合并到一起 消耗的体力等于两堆果子的重量之和 可以
  • Petya and Exam【Codeforces 1282 C】【贪心】

    Codeforces Round 610 Div 2 C 有N道题目 题目有简单与困难之分 简单的题目花费A分钟 困难的题目花费B分钟 那么考试时间一共有T的情况下 我们是可以提前交卷的 但是有些时间限制 就是譬如说你现在第x分钟交卷 但是
  • Polycarp and Div 3【Codeforces Round #496 (Div. 3)【D题】】【贪心】

    应该说是今天凌晨的吧 第一次打Code Forces 懵懵懂懂的 不过感觉还是良好 做了几道签到题 难题还是没有那个水准去做 Polycarp likes numbers that are divisible by 3 He has a h
  • New Year and Social Network【Hello 2020 F】【拓扑+LCA+贪心】

    题目链接 看到比赛的时候zzq大聚聚用了LCT做的 在线 首先 我们可以发现 两棵大小相同 构造形状不同的树 一定是可以用另一棵树的边来维持这棵树上的每一个点的相互连通性的 我的做法 就是基于这样展开的 我们有T1 T2两棵树 现在我们要去
  • HDOJ 1052 Tian Ji -- The Horse Racing

    Tian Ji The Horse Racing Time Limit 2000 1000 MS Java Others Memory Limit 65536 32768 K Java Others Total Submission s 2
  • NYOJ 586 疯牛 & POJ 2456(二分搜索 + 贪心)

    疯牛 时间限制 1000 ms 内存限制 65535 KB 难度 4 描述 农夫 John 建造了一座很长的畜栏 它包括N 2 lt N lt 100 000 个隔间 这些小隔间依次编号为x1 xN 0 lt xi lt 1 000 000
  • 多元Huffman编码问题

    题目链接 题意 最多可以让k堆合并 每一次合并的花费为河合并堆的数量 问最多和最少的花费 题解 最少的花费一定是每次合并的堆数尽可能多 这样我们就会减少前面已经合并的堆的重复计算 所以 每次合并k堆时最少 每次合并2堆时最大 另外 最少的时
  • 2605. 从两个数字数组里生成最小数字

    文章目录 Tag 题目来源 题目解读 解题思路 方法一 枚举比较法 方法二 集合的位运算表示法 写在最后 Tag 贪心 位运算 数组 题目来源 2605 从两个数字数组里生成最小数字 题目解读 给定两个各自只包含数字 1 到 9 的两个数组
  • POJ-3253 Fence Repair

    农夫约翰想修理牧场周围的一小段围栏 他测量围栏并认定他需要 1 20000 厚木板 每一个都具有一些整数长度大号我 1 大号我 50000 单元 然后 他购买一块长板足够长 以便看到N块板 即 其长度是长度L i的总和 FJ忽略了 切口 锯
  • LeetCode-1827. 最少操作使数组递增【贪心,数组】

    LeetCode 1827 最少操作使数组递增 贪心 数组 题目描述 解题思路一 简单暴力 解题思路二 优化1 ans是操作数 mx是当前最大元素 mx无论如何会依次递增 解题思路三 优化2 遇到小的数就pre 1 否则变为num 题目描述
  • HDU--1050:Moving Tables (贪心)

    1 题目源地址 http acm hdu edu cn showproblem php pid 1050 2 解题思路 将每个输入的起始房间和结束房间转换为房间前面的区间 按区间起始位置从小到大排序 首先取第一个区间 后续如果有区间的起始位
  • ACM--田忌赛马--贪心--HDOJ 1052--Tian Ji -- The Horse Racing

    HDOJ题目地址 传送门 Tian Ji The Horse Racing Time Limit 2000 1000 MS Java Others Memory Limit 65536 32768 K Java Others Total S
  • 贪心算法的实现

    您知道谁知道您希望n 个人中的谁来参加聚会 假设 知道 是对称的 如果我认识你 你就认识我 你进一步要求 你希望每个人在聚会上至少有 5 个新朋友 而且 为了让没有人感到太孤立 每个人应该在聚会上已经认识至少 5 个人 您的原始名单可能不满
  • 贪心算法:区间着色

    在间隔调度中 算法是选择最早完成时间 但在间隔着色中 前者不起作用 是否有示例或解释为什么选择最早完成时间不适用于间隔着色 区间着色问题是 给定一组区间 我们想要着色 所有间隔 以便给定相同颜色的间隔不相交 目标是尽量减少使用的颜色数量 这
  • 使用贪婪正则表达式忽略可选后缀

    我正在 NET 中对如下所示的字符串执行正则表达式匹配 1 Lists General Discussion Waffles Win 2 Lists General Discussion Waffles Win 2 000 3 Lists
  • 如何求最大生成树?

    与克鲁斯卡尔最小生成树算法相反的算法是否适用 我的意思是 每一步选择最大权重 边缘 还有其他找到最大生成树的想法吗 是的 它确实 计算网络 G 的最大权生成树的一种方法 由于克鲁斯卡尔 可以总结如下 按权重将 G 的边按降序排序 令 T 为
  • 最大覆盖不相交间隔

    假设您有 k 无法尝试所有可能的子集 2 k 不可行 贪婪方法按 a i 区间覆盖算法 排序 按 b i 最大不相交区间数算法 排序不起作用 不知道是否有动态程序解决方案 考虑到输入的大小 我认为解决方案应该是 O k log k 或 O

随机推荐