题解:学而思编程 蚂蚁

【题目来源】

学而思编程:蚂蚁

【题目描述】

\(n\) 蚂蚁在长度为 \(L\) 单位的木棍上,每只蚂蚁都有一个初始的位置和初始朝向(任意两只蚂蚁的初始位置不同),每只蚂蚁都以每秒一个单位的速度向前移动。其中一部分蚂蚁向左移动,其他蚂蚁向右移动。

当两只向不同方向移动的蚂蚁在某个点相遇时,它们会同时改变移动方向并继续移动。假设更改方向不会花费任何额外时间。

而当蚂蚁在某一时刻 \(t\) 到达木板的一端时,它立即从木板上掉下来,初始时刻 \(t=0\)。请你用编程实现:最后一只蚂蚁从木棍上掉下来的时刻。

【输入】

输入有 \(n+1\) 行,第 \(1\) 行两个正整数 \(n,L\);

\(2\) 行到第 \(n+1\) 行,每行两个整数 \(x_i,d_i\)\(x_i\) 表示第 \(i\) 只蚂蚁的初始位置,\(d_i\) 表示第 \(i\) 只蚂蚁的初始朝向,其中 \(d_i=0\) 表示第 \(i\) 只蚂蚁初始朝向向左,\(d_i=1\) 表示第 \(i\) 只蚂蚁初始朝向向右。

【输出】

输出一个整数 \(t\),最后一只蚂蚁从木棍上掉下来的时刻。

【输入样例】

4 4
0 1
1 1
3 0
4 0

【输出样例】

4

【核心思想】

  1. 问题分析:给定 \(n\) 只蚂蚁在长度为 \(L\) 的木棍上,每只蚂蚁初始位置为 \(x_i\),朝向 \(d_i\)\(0\) 向左,\(1\) 向右),速度均为 \(1\) 单位/秒。两只蚂蚁相遇时改变方向,求最后一只蚂蚁掉落的时刻。这是一个碰撞等效转化问题,关键在于发现蚂蚁碰撞后改变方向等价于"穿透"继续直行。

  2. 算法选择

    • 穿透等效法:将碰撞后掉头等效为两只蚂蚁互相穿透继续原方向移动,因为蚂蚁不可区分,碰撞不改变蚂蚁集合的运动状态
    • 极值统计:每只蚂蚁的掉落时间只取决于其到对应端点的距离,与碰撞无关
  3. 关键步骤

    • 读取输入:读取 \(n\)(蚂蚁数量)、\(L\)(木棍长度)
    • 初始化\(ans = 0\)(记录最大掉落时间)
    • 逐只处理(循环 \(n\) 次):
      • 读取 \(x_i\)(位置)、\(d_i\)(朝向)
      • 计算掉落时间
        • \(d_i = 0\)(向左):掉落时间 \(t_i = x_i\)(到左端点距离)
        • \(d_i = 1\)(向右):掉落时间 \(t_i = L - x_i\)(到右端点距离)
      • 更新最大值:若 \(t_i > ans\),则 \(ans \leftarrow t_i\)
    • 输出结果\(ans\) 即为最后一只蚂蚁的掉落时刻
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),只需遍历 \(n\) 只蚂蚁各一次
    • 空间复杂度:\(O(1)\),仅使用 \(ans\) 变量,无需存储蚂蚁信息
  5. 穿透等效的核心思想

    • 碰撞不变性:两只蚂蚁碰撞后掉头,与它们互相穿透继续直行,在宏观效果上等价。因为蚂蚁完全相同,无法区分哪只是哪只,碰撞只是交换了两只蚂蚁的"身份"
    • 问题降维:将复杂的碰撞交互问题转化为简单的单蚂蚁运动问题,每只蚂蚁独立计算到端点的距离即可
    • 方向分离:向左的蚂蚁只关心到左端点距离 \(x_i\),向右的蚂蚁只关心到右端点距离 \(L - x_i\),两者互不干扰
    • 全局最优:最后一只掉落的时间是所有蚂蚁掉落时间的最大值,即 \(\max(\max_{d_i=0} x_i, \max_{d_i=1} (L - x_i))\)
    • 适用于不可区分粒子碰撞、运动等效转化类问题

【解题思路】

【算法标签】

模拟

【代码详解】

#include <bits/stdc++.h>
using namespace std;

int main()
{
    // 输入n(物品数量)和L(总长度)
    int n, L;
    cin >> n >> L;

    // 初始化最大距离ans为0
    int ans = 0;

    // 遍历每个物品
    for (int i = 1; i <= n; i++)
    {
        // 输入物品的位置x和方向d
        int x, d;
        cin >> x >> d;

        // 根据物品方向处理
        if (d == 0)
        {
            // 方向为0(向左):最大距离就是x本身
            if (x > ans)
            {
                ans = x;
            }
        }
        else
        {
            // 方向为1(向右):最大距离是L-x
            if (L - x > ans)
            {
                ans = L - x;
            }
        }
    }

    // 输出所有物品中的最大距离
    cout << ans;

    return 0;
}

【运行结果】

4 4
0 1
1 1
3 0
4 0
4
posted @ 2026-07-05 17:20  团爸讲算法  阅读(15)  评论(0)    收藏  举报