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

3661 可以被机器人摧毁的最大墙壁数目:离散化与线段树解法

综述由AI生成解决 LeetCode 3661 问题。题目要求在直线上分布的机器人和墙壁中,计算机器人子弹能摧毁的最大墙壁数。机器人子弹射程受限且会被其他机器人阻挡。文章分析了动态规划结合线段树(或树状数组)的解法,重点讨论了如何处理重叠射击范围导致的重复统计问题。针对坐标范围大的情况,提出了离散化优化方案以节省内存。提供了错误解法、内存超限解法及最终优化后的 C++ 实现代码。

禅心发布于 2026/4/5更新于 2026/5/3033 浏览
3661 可以被机器人摧毁的最大墙壁数目:离散化与线段树解法

3661. 可以被机器人摧毁的最大墙壁数目

一条无限长的直线上分布着一些机器人和墙壁。给你整数数组 robots,distance 和 walls:

  • robots[i] 是第 i 个机器人的位置。
  • distance[i] 是第 i 个机器人的子弹可以行进的最大距离。
  • walls[j] 是第 j 堵墙的位置。

每个机器人有一颗子弹,可以向左或向右发射,最远距离为 distance[i] 米。子弹会摧毁其射程内路径上的每一堵墙。机器人是固定的障碍物:如果子弹在到达墙壁前击中另一个机器人,它会立即在该机器人处停止,无法继续前进。

返回机器人可以摧毁墙壁的最大数量。 注意:墙壁和机器人可能在同一位置;该位置的墙壁可以被该位置的机器人摧毁。机器人不会被子弹摧毁。

示例

示例 1: 输入:robots = [4], distance = [3], walls = [1,10] 输出:1 解释:robots[0] = 4 向左发射,distance[0] = 3,覆盖范围 [1, 4],摧毁了 walls[0] = 1。因此,答案是 1。

示例 2: 输入:robots = [10,2], distance = [5,1], walls = [5,2,7] 输出:3 解释:robots[0] = 10 向左发射,distance[0] = 5,覆盖范围 [5, 10],摧毁了 walls[0] = 5 和 walls[2] = 7。robots[1] = 2 向左发射,distance[1] = 1,覆盖范围 [1, 2],摧毁了 walls[1] = 2。因此,答案是 3。

示例 3: 输入:robots = [1,2], distance = [100,1], walls = [10] 输出:0 解释:在这个例子中,只有 robots[0] 能够到达墙壁,但它向右的射击被 robots[1] 挡住了,因此答案是 0。

错误解法:线段树 + 动态规划

动态规划的状态表示

dp[i] 表示只摧毁位置 ≤ i 的墙,最后能销毁多少堵墙。且之后不会消耗 ≤ i 的墙。 最大值线段树 maxTree 记录最大值。

动态规划的顺序

按机器人的位置从小到大处理。

动态规划的转移方程

每个机器人枚举两种状态,向左射击,向右射击。

动态规划的初始值

全为 0。

动态规划的返回值

maxTree 的最大值。

错误原因

由于两个机器人的射击范围不能重叠,否则会重复统计。故向左射击不一定是最大射程,各射程要一一枚举。 例如:robots = { 4,10 }, distance = { 3,3 }, walls = { 6,7,8 };第二个机器人向左射击能到 {7,8,9,10}。第一个机器人向右射击到 7,第二个机器人向左射击到 8,才是正解。

template <class TSave, class TRecord>
class CRangUpdateLineTree {
protected:
    virtual void OnQuery(TSave& ans, const TSave& save, const int& iSaveLeft, const int& iSaveRight) = 0;
    virtual void OnUpdate(TSave& save, const int& iSaveLeft, const int& iSaveRight, const TRecord& update) = 0;
    virtual void OnUpdateParent(TSave& par, const TSave& left, const TSave& r, const int& iSaveLeft, const int& iSaveRight) = 0;
    virtual void OnUpdateRecord(TRecord& old, const TRecord& newRecord) = 0;
};
// ... (此处省略部分类定义以保持简洁,逻辑同上)

正确解法

某个向右的机器人和某个向左的机器人射程重叠后。向右的机器人射程不变,向左的机器人缩短射程使之不重叠。向右射击仍然是一种状态,故只讨论向左。 令向左的机器人位于 x2,向左能射击到 x1。 则:射程非最大向左的最大值为 max_{x1}^{x2-1}(dp[x] + f(x)),其中 f(x) 是处于 x+1 ~ x2 的墙数。令 g(x) 是 ≤ x 的墙数。 则 射程非最大向左的最大值为 max_{x1}^{x2-1}(dp[x] + g(x2) - g(x)) = g(x2) + max_{x1}^{x2-1}(dp[x] - g(x))。 我们用最大值线段树 maxTree2 记录:dp[x] - g(x)。 向左射击的最大值为:max(射程非最大向左的最大值,射程最大向左的最大值)。

内存超限代码

template <class TSave, class TRecord>
class CSingeUpdateLineTree {
protected:
    virtual void OnQuery(TSave& ans, const TSave& cur) = 0;
    // ... 其他虚函数
};
// ... 实现细节

空间超限的解决方法

一、离散化。 二、改用最大值树状数组。

核心代码

template <class T = int>
class CDiscretize {
public:
    CDiscretize(vector<T> nums) {
        sort(nums.begin(), nums.end());
        nums.erase(std::unique(nums.begin(), nums.end()), nums.end());
        m_nums = nums;
        for (int i = 0; i < nums.size(); i++) {
            m_mValueToIndex[nums[i]] = i;
        }
    }
    int operator[](const T value) const {
        auto it = m_mValueToIndex.find(value);
        if (m_mValueToIndex.end() == it) return -1;
        return it->second;
    }
    int size() const { return m_mValueToIndex.size(); }
    vector<T> m_nums;
protected:
    unordered_map<T, int> m_mValueToIndex;
};
// ... 线段树及 Solution 实现

简单版

性质一:如果机器人和墙挨着一起,此墙一定被摧毁。故只考虑不挨着机器人的墙。 性质二:由于子弹遇到机器人会停止,故墙只会被相邻的机器人摧毁。

动态规划的状态表示

dp0n 表示第 0 ~ i 号机器人都已经射击完毕,且最后一个机器人向左(右)射击能摧毁最后的墙数。 空间复杂度:O(n) 为了方便处理边界情况,增加一个机器人标兵,射击距离都是 0,位置分别在正负无穷大。

动态规划的填表顺序

n = 1 to N 枚举后继状态和选择。

动态规划的转移方程

如果 i-1 和 i 都向左射击,两者不会摧毁同一道墙。 如果 i-1 向右和 i 向左射击,两者可能摧毁同一道墙。需要去重。i 向右能够摧毁 g1 道墙,i-1 向左能够摧毁 g0 道墙,i 和 i-1 之间的机器人数量 c,则重复的墙数为:max(0, g1 + g0 - c)。 如果 i 向右射击,i-1 无论向左还是向右,两者都不会摧毁同一道墙。

代码

class Solution {
public:
    int maxWalls(vector<int>& robots, vector<int>& distance, vector<int>& walls) {
        const int N = robots.size();
        const int M = int(1e9 + 1e5 + 1);
        sort(walls.begin(), walls.end());
        vector<pair<int, int>> rd;
        for (int i = 0; i < N; i++) {
            rd.emplace_back(robots[i], distance[i]);
        }
        rd.emplace_back(INT_MIN / 2, 0);
        rd.emplace_back(INT_MAX / 2, 0);
        sort(rd.begin(), rd.end());
        // ... 后续逻辑
    }
};

单元测试

vector<int> robots, distance, walls;
TEST_METHOD(TestMethod00) {
    robots = {4,10}, distance = {3,3}, walls = {6,7,8};
    auto res = Solution().maxWalls(robots, distance, walls);
    AssertEx(3, res);
}
// ... 更多测试用例

测试环境

操作系统:win7/win10 开发环境:VS2019/VS2022 C++17 如无特殊说明,本算法用 C++ 实现。

目录

  1. 3661. 可以被机器人摧毁的最大墙壁数目
  2. 示例
  3. 错误解法:线段树 + 动态规划
  4. 动态规划的状态表示
  5. 动态规划的顺序
  6. 动态规划的转移方程
  7. 动态规划的初始值
  8. 动态规划的返回值
  9. 错误原因
  10. 正确解法
  11. 内存超限代码
  12. 空间超限的解决方法
  13. 核心代码
  14. 简单版
  15. 动态规划的状态表示
  16. 动态规划的填表顺序
  17. 动态规划的转移方程
  18. 代码
  19. 单元测试
  20. 测试环境
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Stable Diffusion 与 ComfyUI 整合包安装及常见问题指南
  • Web 安全实战:robots.txt 协议原理、利用与防御策略
  • Claude Code的完美平替:OpenCode + GitHub Copilot
  • C++ 刷题与学习资源网站汇总
  • 基于 DeepFace 与 OpenCV 的实时情绪分析器
  • MySQL DAYOFWEEK 函数详解:获取星期索引值
  • Spring Boot + Vue 前后端接口交互全流程详解
  • OpenClaw Docker 部署指南:集成飞书钉钉 QQ 企业微信机器人
  • MySQL 数据类型详解
  • 使用 AI 工具(Cursor/VS Code)调试 MATLAB 代码实测
  • 从 LLaMA-Factory 微调到高通 NPU 部署:Qwen-0.6B 全链路移植指南
  • Qt Creator 接入外部 AI 大模型配置指南
  • AIGC 爆款视频《牌子》创作方法论与逐帧分析
  • OpenVLA 深度解析:基于 Prismatic VLM 的离散化动作预测方案
  • FPGA PCIe XDMA Link Up 失败调试:基于 LTSSM 状态机定位问题
  • Supabase 实战指南:数据库、SDK 与本地部署
  • SkyWalking 告警通知渠道集成:Webhook、Slack、钉钉、企业微信
  • 高并发内存池大页内存申请释放及定长内存池优化
  • 网络安全行业人才缺口与薪资前景分析
  • 法奥机器人基础操作与编程指南

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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