跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

二分答案专题实战:木材加工与砍树问题详解

二分答案通过判定函数将最优化问题转化为可行性判断。讲解木材加工与砍树两道经典例题,核心在于利用解空间的单调性进行二分查找。木材加工需计算切割段数是否满足需求,砍树问题则关注伐木高度与产出木材量的关系。两者均使用 C++ 实现,通过调整二分边界寻找最优解。掌握此类模板可高效解决最大值最小或最小值最大类问题。

战神发布于 2026/3/25更新于 2026/9/856 浏览
二分答案专题实战:木材加工与砍树问题详解

二分答案专题实战:木材加工与砍树问题详解

二分答案是算法竞赛与笔试中极具技巧性的高分解法,核心思路是将复杂求解转化为简洁的二分 + 判定。它专门解决「最大值最小」「最小值最大」等经典问题。如果解空间在从小到大的变化过程中,判断答案的结果出现二段性,此时我们就可以二分这个解空间,通过判断找出最优解。

一、木材加工

题目描述

给定 n 根原木,长度分别为 a[1]...a[n]。要求切割出 k 段长度相等的木料,求每段的最大可能长度。

解题思路

这道题是典型的二分答案模型。假设我们切出的长度为 x,那么对于每一根原木 a[i],能切出的段数是 a[i] / x。总段数就是所有原木切出段数的和。如果总段数 >= k,说明长度 x 可行,可以尝试更大的长度;否则需要减小长度。

这里的关键在于单调性:随着 x 增大,能切出的总段数必然减少。因此存在一个临界点,满足二段性,适合二分查找。

代码实现

#include <iostream>
using namespace std;

const int N = 1e5 + 10;
typedef long long LL;

LL a[N], n, k;

// 计算在切割长度为 x 的情况下能切几段
LL calc(LL x) {
    if (x == 0) return 0; // 防止除零错误
    LL cnt = 0;
    for (int i = 1; i <= n; i++) {
        cnt += a[i] / x;
    }
    return cnt;
}

int main() {
    cin >> n >> k;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    
    // 二分边界:左边界为 0(或 1),右边界设为足够大,如 1e8
    int l = 0, r = 1e8;
    while (l < r) {
        // 向上取整,避免死循环
        LL mid = (l + r + 1) / 2;
        if (calc(mid) >= k) {
            l = mid; // 可行,尝试更大的长度
        } else {
            r = mid - 1; // 不可行,减小长度
        }
    }
    cout << l << endl;
    return 0;
}

二、砍树

题目描述

给定 n 棵树的高度,使用伐木机进行砍伐。设定一个高度 H,高于 H 的部分被砍下。要求砍下的木材总量至少为 M,求 H 的最大值。

解题思路

设伐木机的高度为 H,能得到的木材量为 C。根据题意可以发现明显的单调性:

  • 当 H 增大的时候,C 在减小。
  • 当 H 减小的时候,C 在增大。

我们需要找到最大的 H,使得 C >= M。这与木材加工问题的逻辑完全一致,只是计算方式不同。对于每棵树 a[i],如果 a[i] > H,则贡献 a[i] - H 的木材。

代码实现

#include <iostream>
using namespace std;

const int N = 1e6 + 10;
typedef long long LL;

LL a[N], n, m;

// 计算高度为 mid 时能得到的木材量
LL calc(LL mid) {
    LL ret = 0;
    for (int i = 1; i <= n; i++) {
        if (a[i] - mid > 0) {
            ret += a[i] - mid;
        }
    }
    return ret;
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
    }
    
    // 二分边界:高度最小为 1,最大可达 2e9
    LL l = 1, r = 2e9;
    while (l < r) {
        LL mid = (l + r + 1) / 2;
        if (calc(mid) >= m) {
            l = mid; // 木材够多,尝试更高的高度
        } else {
            r = mid - 1; // 木材不够,降低高度
        }
    }
    cout << l << endl;
    return 0;
}

总结

二分答案的关键,是抓住解空间的二段性,通过二分缩小范围、用判断函数验证合法性。这两道题虽然场景不同,但本质都是利用单调性将最优化问题转化为可行性判断。掌握这一思维,不仅能拿下算法题,更能学会用逻辑拆解难题。在实际刷题中,注意处理边界条件(如除零、溢出)以及二分的上下界设置,就能稳稳地拿到分数。

目录

  1. 二分答案专题实战:木材加工与砍树问题详解
  2. 一、木材加工
  3. 题目描述
  4. 解题思路
  5. 代码实现
  6. 二、砍树
  7. 题目描述
  8. 解题思路
  9. 代码实现
  10. 总结

更多推荐文章

查看全部
  • Rust 语言的前世今生与核心技术解析
  • Meta:BackTranslation 与 IBM Self Alignment 技术解析
  • Llama Factory 微调:如何选择最佳超参数
  • 硕士论文盲审前如何降低 AI 检测率及评委关注点分析
  • OpenClaw 配置飞书机器人教程
  • ComfyUI-Manager 插件管理工具使用指南
  • LLM 训练微调实战:基于 LLaMA-Factory 框架详解
  • AI 辅助 9·1 软件安装:环境检测与问题修复方案
  • 前端微前端架构实践:避免巨石应用陷阱
  • AIGC 背景下图文内容社区数据指标体系构建指南
  • Vue3 ElementUI TypeScript 设置 style 属性类型检查失败解决方案
  • Spring Boot 3.5.9:工程视角下的稳定性演进与实战价值
  • OpenCode:开源版 Claude Code,支持多模型与远程终端
  • Windows 下使用 uv 从零配置 Python (OpenCV) 环境
  • GitHub Copilot 代理配置与网络优化指南
  • 双指针算法实战:有效三角形与多数之和
  • OpenClaw Zero Token 基于浏览器自动化实现大模型免 Token 调用
  • Unity MCP 指南:使用 AI 控制 Unity 编辑器
  • 论文阅读:Vision-Language-Action (VLA) 模型概念、进展与应用挑战
  • 前端文件下载实战:从原理到最佳实践

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online