见:P1577 切绳子 - 洛谷

题目描述

有 N 条绳子,它们的长度分别为 Li​。如果从它们中切割出 K 条长度相同的绳子,这 K 条绳子每条最长能有多长?答案保留到小数点后 2 位(直接舍掉 2 位后的小数)。

输入格式

第一行两个整数 N 和 K,接下来 N 行,描述了每条绳子的长度 Li​ 。

输出格式

切割后每条绳子的最大长度。答案与标准答案误差不超过 0.01 或者相对误差不超过 1% 即可通过。

输入输出样例

in:
4 11
8.02
7.43
4.57
5.39
out:
2.00

说明/提示

对于 100% 的数据 0<Li​≤100000.00,0<n≤10000,0<k≤10000

第一步

code

#include<bits/stdc++.h>
using namespace std;
const int q=1e4+5;
int n,k;
double z[q];bool ch(double x){int ans=0;for(int i=0;i<n;i++){ans+=floor(z[i]/x);if(ans>=k) return true;}return false;
}int main(){cin>>n>>k;for(int i=0;i<n;i++) cin>>z[i];double l=0,r=1e9;while(r-l>=1e-4){double mid=l+(r-l)/2;if(ch(mid)) l=mid;else r=mid;}printf("%.2f",floor(l*100)/100);return 0;
}

第二步

分析

问题背景与应用场景

这个问题在现实生活中有很多应用场景,比如:

  • 电缆切割:将不同长度的电缆切割成若干等长的小段,以满足至少k段的需求,同时最大化每段的长度。
  • 土地划分:将不同面积的土地划分为至少k块相等面积的小地块,求最大可能的地块面积。
  • 布料裁剪:将不同长度的布料裁剪成至少k条等长的布条,以最大化每条布条的长度。

代码详细分析

全局变量与常量定义
const int q=1e4+5;
int n,k;
double z[q];
  • q是一个常量,表示数组的最大长度,这里设置为 10005,足够处理题目中可能出现的最大数据量。
  • nk是两个整数变量,分别表示材料的数量和需要切割出的段数。
  • z[q]是一个双精度浮点数数组,用于存储每个材料的长度。
核心判断函数ch(double x)
bool ch(double x){int ans=0;for(int i=0;i<n;i++){ans+=floor(z[i]/x);if(ans>=k) return true;}return false;
}

这个函数的作用是判断是否可以将所有材料切割成至少k段,每段长度为x。具体逻辑如下:

  1. 初始化计数器ans为 0。
  2. 遍历每个材料,计算该材料可以切割出多少段长度为x的小段,使用floor(z[i]/x)确保结果为整数。
  3. 累加每段材料可切割的段数到ans中。
  4. 如果在遍历过程中发现ans已经达到或超过k,则立即返回true,表示可以切割出足够的段数。
  5. 如果遍历完所有材料后ans仍小于k,则返回false
主函数main()
int main(){cin>>n>>k;for(int i=0;i<n;i++) cin>>z[i];double l=0,r=1e9;while(r-l>=1e-4){double mid=l+(r-l)/2;if(ch(mid)) l=mid;else r=mid;}printf("%.2f",floor(l*100)/100);return 0;
}

主函数实现了二分查找算法,用于找到最大的可行切割长度,具体步骤如下:

  1. 读取输入数据:首先读取材料数量n和需要切割的段数k,然后读取每个材料的长度并存储在数组z中。
  2. 初始化二分查找的左右边界:左边界l初始化为 0,右边界r初始化为一个足够大的值(1e9),确保包含所有可能的答案。
  3. 执行二分查找:在r-l >= 1e-4的条件下循环,这个条件控制了二分查找的精度,当左右边界的差距小于 1e-4 时停止循环。
  4. 计算中间值mid:使用l + (r - l) / 2计算中间值,避免直接使用(l + r) / 2可能导致的溢出问题。
  5. 判断中间值是否可行:调用ch(mid)函数,如果返回true,说明中间值mid是一个可行解,更新左边界l = mid;否则更新右边界r = mid
  6. 输出结果:循环结束后,l的值即为所求的最大可行切割长度,但需要保留两位小数。使用floor(l*100)/100确保结果精确到小数点后两位,然后使用printf("%.2f", ...)输出结果。

算法思路与二分查找的应用

这个问题的核心思路是利用二分查找来高效地找到最优解。二分查找适用于这种最大化最小值或最小化最大值的问题,其关键在于能够快速判断一个给定的值是否可行。

具体来说,二分查找的应用场景需要满足以下条件:

  1. 解空间具有单调性:在这个问题中,如果长度x是可行的,那么所有小于x的长度也都是可行的;反之,如果长度x不可行,那么所有大于x的长度也都不可行。
  2. 存在明确的判断条件:通过ch函数可以快速判断一个给定的长度是否可行。

二分查找的时间复杂度是 O (log (max_length)),其中 max_length 是右边界的值。在每次迭代中,需要遍历所有材料一次,时间复杂度为 O (n),因此总的时间复杂度为 O (n log (max_length)),这使得算法在处理大规模数据时仍然高效。

精度控制与输出处理

在处理浮点数二分查找时,精度控制是一个关键问题。代码中使用r - l >= 1e-4作为循环条件,确保结果的精度在小数点后四位。这是因为在实际应用中,我们通常只需要保留两位小数的结果,而额外的精度可以避免由于浮点数计算误差导致的结果偏差。

输出处理部分使用了floor(l*100)/100来确保结果精确到小数点后两位。这是因为直接使用%.2f格式化输出可能会进行四舍五入,而题目要求是直接截断到两位小数。例如,如果计算结果是 3.149,floor(3.149*100)/100会得到 3.14,而不是 3.15。

代码优化与扩展

输入验证

当前代码没有对输入进行验证,在实际应用中可以添加输入验证以增强代码的健壮性。例如:

if (k <= 0) {cout << "Error: k must be a positive integer." << endl;return 1;
}
右边界优化

初始右边界设置为 1e9 可能过大,可以根据输入数据动态设置右边界,例如:

double max_z = 0;
for(int i=0;i<n;i++) {cin>>z[i];max_z = max(max_z, z[i]);
}
double l=0, r=max_z;

这样可以减少二分查找的迭代次数,提高效率。

处理无解情况

如果所有材料的总长度小于k,则无论如何都无法切割出k段,此时应输出 0。可以在开始时添加检查:

double sum = 0;
for(int i=0;i<n;i++) {sum += z[i];
}
if (sum < k) {cout << "0.00" << endl;return 0;
}
代码可读性优化

可以添加注释来提高代码的可读性,例如:

// 检查是否可以将所有材料切割成至少k段,每段长度为x
bool ch(double x){// ... 函数体 ...
}// 主函数:二分查找最大可行切割长度
int main(){// ... 主函数体 ...
}

复杂度分析

  • 时间复杂度:O (n log (max_length)),其中 n 是材料的数量,max_length 是右边界的值。
  • 空间复杂度:O (n),主要用于存储材料长度的数组。

测试用例

以下是一些测试用例,可以帮助验证代码的正确性:

  1. 基本测试

    • 输入:n=3, k=4z=[10, 20, 30]
    • 输出:15.00
    • 解释:每段长度为 15 时,可切割出0+1+2=3段,不足 4 段;每段长度为 14 时,可切割出0+1+2=3段,不足 4 段;每段长度为 13 时,可切割出0+1+2=3段,不足 4 段;每段长度为 12 时,可切割出0+1+2=3段,不足 4 段;每段长度为 11 时,可切割出0+1+2=3段,不足 4 段;每段长度为 10 时,可切割出1+2+3=6段,满足条件,且为最大可行长度。
  2. 边界测试

    • 输入:n=1, k=1z=[5.0]
    • 输出:5.00
    • 解释:只有一段材料,长度为 5,切割成 1 段,最大长度为 5。
  3. 精度测试

    • 输入:n=2, k=3z=[1.0, 2.0]
    • 输出:0.66
    • 解释:每段长度为 0.66 时,可切割出1+3=4段,满足条件;每段长度为 0.67 时,可切割出1+2=3段,满足条件,但 0.67 不是最大可行长度,最大可行长度为 0.666...,截断后为 0.66。

总结

这段代码通过二分查找高效地解决了材料切割的最大化最小值问题,关键在于合理设计判断函数ch和精确控制二分查找的边界与精度。代码结构清晰,算法效率高,适用于处理大规模数据。在实际应用中,可以根据具体需求进行进一步优化和扩展,如添加输入验证、处理无解情况等,以提高代码的健壮性和实用性。


完结撒花hi✿(。◕ᴗ◕。)✿ 

对了

听说给点赞+关注+收藏的人会发大财哦(o゚▽゚)o  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/88451.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/88451.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/88451.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

imx6ull-裸机学习实验16——I2C 实验

目录 前言 I2C简介 基本特性​​ I2C 协议 起始位 停止位 数据传输 应答信号 I2C 写时序 I2C 读时序 I.MX6U I2C 简介 寄存器 地址寄存器I2Cx_IADR(x1~4) 分频寄存器I2Cx_IFDR 控制寄存器I2Cx_I2CR 状态寄存器I2Cx_I2SR 数据寄存器I2Cx_I2DR AP3216C 简介 …

【TCP/IP】5. IP 协议

5. IP 协议5. IP 协议5.1 概述5.2 IP 数据报格式5.3 无连接数据报传输5.3.1 首部校验5.3.2 数据分片与重组5.4 IP 数据报选项5.4.1 选项格式5.4.2 选项类型5.5 IP 模块的结构本章要点5. IP 协议 5.1 概述 IP 协议是 TCP/IP 协议簇的核心协议&#xff0c;位于网络层&#xff0…

Linux 服务器挖矿病毒深度处理与防护指南

在 Linux 服务器运维中&#xff0c;挖矿病毒是常见且危害较大的安全威胁。此类病毒通常会隐蔽占用大量 CPU 资源进行加密货币挖矿&#xff0c;导致服务器性能骤降、能耗激增&#xff0c;甚至被黑客远程控制。本文将从病毒特征识别、应急处理流程、深度防护措施三个维度&#xf…

MySQL数据表设计 系统的营销功能 优惠券、客户使用优惠券的设计

系统的营销功能营销功能概述&#xff1a;系统的营销功能主要是&#xff1a;市场活动管理、营销自动化、销售线索管理以及数据分析和报告等。‌ToC‌&#xff08;Consumer&#xff09;&#xff1a;面向个人消费者&#xff0c;满足日常消费需求。‌优惠券的种类&#xff1a;ToC的…

让 3 个线程串行的几种方式

1、通过join()的方式 子线程调用join()的时候&#xff0c;主线程等待子线程执行完再执行。如果让多个线程顺序执行的话&#xff0c;那么需要他们按顺序调用start()。/*** - 第一个迭代&#xff08;i0&#xff09;&#xff1a;* 启动线程t1 -> 然后调用t1.join()。* …

在 Vue 项目中关闭 ESLint 规则

在 Vue 2 项目中关闭 ESLint 规则有以下几种方法&#xff0c;根据您的需求选择合适的方式&#xff1a; 1. 完全禁用 ESLint 修改 vue.config.js&#xff08;推荐&#xff09; module.exports {// 关闭 ESLintlintOnSave: false }或修改 package.json {"scripts": {&…

电脑息屏工具,一键黑屏超方便

软件介绍 今天为大家推荐一款实用的PC端屏幕管理工具——CloseDsp。这款"息屏小能手"能一键关闭显示器&#xff0c;解决各种场景下的屏幕管理需求。 核心功能 CloseDsp最突出的特点是能瞬间关闭显示器屏幕。只需点击"关闭显示器"按钮&#xff0c;屏幕…

嵌入式调试LOG日志输出(以STM32为例)

引言在嵌入式系统开发中&#xff0c;调试是贯穿整个生命周期的关键环节。与传统PC端程序不同&#xff0c;嵌入式设备资源受限&#xff08;如内存、存储、处理器性能&#xff09;&#xff0c;且运行环境复杂&#xff08;无显示器、键盘&#xff09;&#xff0c;传统的断点调试或…

Zephyr的设备驱动模型

默认配置默认配置 boards/arm/nucleo_f401re/ ├── nucleo_f401re.dts ← 板卡设备树主入口 ├── nucleo_f401re_defconfig ← 默认 Kconfig 配置 ├── board.cmake ← CMake 构建入口overlay1.新增加驱动需要修改对应板的设备树文件&#xf…

Mysql字段没有索引,通过where x = 3 for update是使用什么级别的锁

没有索引时&#xff0c;FOR UPDATE 会锁住整个表 现在&#xff0c;你正在一本一本地翻看所有书&#xff0c;寻找“维修中”的书&#xff0c;并且你对管理员说&#xff1a;“在我清点和修改完之前&#xff0c;别人不能动这些书&#xff0c;也不能往这个范围里加新书&#xff01;…

TCP-与-UDP-协议详解:原理、区别与应用场景全解析

TCP 与 UDP 协议详解&#xff1a;原理、区别与应用场景全解析 在日常使用网络的过程中&#xff0c;我们经常听到 TCP 和 UDP 这两个词。你打开网页、发送消息、观看视频&#xff0c;背后都在使用 TCP 或 UDP 进行数据传输。那么这两个协议到底是怎么工作的&#xff1f;它们之间…

GitHub信息收集

目录 简介 一、入门搜索技巧 1. 基本关键词搜索 2. 文件类型限定搜索 3. 用户/组织定向搜索 二、精准定位技巧 1. 组合搜索条件 2. 排除干扰结果 3. 路径限定搜索 三、防御建议 四、法律与道德提醒 简介 GitHub作为全球最大的代码托管平台&#xff0c;存储着数十亿…

由 DB_FILES 参数导致的 dg 服务器无法同步问题

由 DB_FILES 参数导致的 dg 服务器无法同步问题 用户反映&#xff0c;dg 服务器数据从昨晚&#xff08;7月8日&#xff09;开始停止同步。 连接服务器发现没有 mrp 进程&#xff0c;并且 OPEN_MODE 参数也不正确。具体情况如下所示&#xff1a; SQL> select process, status…

Go语言泛型-泛型对代码结构的优化

在Go语言中,Go泛型-泛型对代码结构的优化部分主要探讨了泛型如何帮助我们优化代码结构、减少重复代码,并提高代码的可维护性、可读性和复用性。以下是详细内容: 一、引言 Go 1.18 引入了泛型,极大地提高了语言的灵活性。泛型使得我们可以编写更加通用、可复用且类型安全的…

【1-快速上手】

文章目录前言简介什么是 Konva&#xff1f;安装 Konva概述它是如何工作的&#xff1f;基本形状样式事件拖放滤镜动画选择器序列化与反序列化性能前言 结合项目实际业务需求&#xff0c;在 Fabric、Konva 等图形化框架中&#xff0c;我选择了性能表现好的 Konva。首先去学习官方…

【LeetCode】209. 长度最小的子数组(前缀和 + 二分)

【LeetCode】209. 长度最小的子数组&#xff08;前缀和 二分&#xff09;题目描述前缀和二分优化前缀和总结二分总结题目描述 题目链接&#xff1a;【LeetCode】209. 长度最小的子数组&#xff08;前缀和 二分&#xff09; 给定一个含有 n 个整数的数组和一个整数 target。…

文件系统----底层架构

当我们谈到文件系统的时候&#xff0c;最重要的点在于&#xff1a;文件的内容与属性是如何存储在磁盘中的&#xff1f;以及操作系统是如何精准定位到这些文件内容的&#xff1f;在谈及文件的内核前&#xff0c;我们先来了解一下储存文件的硬件-----硬盘一.理解硬件首先我们来看…

小程序开发平台,自主开发小程序源码系统,多端适配,带完整的部署教程

温馨提示&#xff1a;文末有资源获取方式全开源与自主开发源码完全开放&#xff1a;开发者可自由修改前端界面、后端逻辑及数据库结构&#xff0c;支持深度定制&#xff08;如调整用户端交互流程、商家端管理功能等&#xff09;。技术栈透明&#xff1a;基于主流技术&#xff0…

stp拓扑变化分类

Max Age 20sHellotime 2sForward delay 153、拓扑改变需要多长时间1&#xff09;根桥故障&#xff1a;需要50秒&#xff08;Max age2个forwarding delay&#xff09;2&#xff09;非直连链路&#xff1a;非直连故障在稳定的STP网络&#xff0c;非根桥会定期收到来自根桥的BPDU报…

一、深度学习——神经网络

一、神经网络 1.神经网络定义&#xff1a;人工神经网络&#xff08;Artificial Neural Network&#xff0c;ANN&#xff09;也简称为神经网络&#xff08;NN&#xff09;&#xff0c;是一种模仿生物神经网络结构和功能的计算模型。人脑可以看作是一个生物神经网络&#xff0c;由…