题解:学而思编程 蚂蚁碰撞

【题目来源】

学而思编程:蚂蚁碰撞

【题目描述】

在一个无限长的木板上有 \(n\) 只蚂蚁正在移动。蚂蚁按照从左到右的顺序从 \(1\)\(n\) 编号,每只蚂蚁都在一个与其他蚂蚁互不相同的位置上。

初始时,每只蚂蚁都有一个初始朝向:\(L\) 表示向左移动,\(R\) 表示向右移动,\(S\) 表示静止不动。每只蚂蚁的移动时的速度相同,然而在移动过程中部分蚂蚁之间会产生碰撞,在两只蚂蚁发生碰撞之后,都会停留在碰撞的位置无法再继续移动。所有蚂蚁不能改变它们的移动方向和状态。

现在给定所有蚂蚁的初始朝向,请你计算所有蚂蚁在木板上发生的碰撞总次数。碰撞次数按照一下方式计算:

  1. 当两只移动方向相反的蚂蚁相撞时,碰撞次数加 \(2\)
  2. 当一只移动的蚂蚁和一只静止的蚂蚁相撞时,碰撞次数加 \(1\)

【输入】

一行一个字符串 \(dir\),表示所有蚂蚁的初始朝向,保证 \(dir\) 只包含 \(L\)\(R\)\(S\)

【输出】

一行一个整数,表示所有蚂蚁在木板上发生的碰撞总次数。

【输入样例】

RLRSLL

【输出样例】

5

【核心思想】

  1. 问题分析:给定 \(n\) 只蚂蚁的初始朝向序列(L 向左、R 向右、S 静止),蚂蚁速度相同且碰撞后停止。碰撞规则为:相向碰撞(RL)次数加 \(2\),移动与静止碰撞(R/LS)次数加 \(1\)。求总碰撞次数。这是一个字符串分析 + 贪心边界裁剪问题,关键在于识别有效碰撞区域并统计其中的移动蚂蚁数量。

  2. 算法选择

    • 边界裁剪:去掉前缀所有 L(这些蚂蚁向左走,左侧无蚂蚁,不会碰撞)和后缀所有 R(这些蚂蚁向右走,右侧无蚂蚁,不会碰撞)
    • 有效区域统计:裁剪后的中间区域内,所有非静止蚂蚁 RL 必然参与至少一次碰撞
  3. 关键步骤

    • 读取朝向字符串 dir
    • 左边界裁剪
      • 指针 l\(0\) 开始右移,跳过所有前缀 L
      • 这些 L 向左移动,左侧无蚂蚁,不会与任何蚂蚁碰撞
    • 右边界裁剪
      • 指针 r 从末尾开始左移,跳过所有后缀 R
      • 这些 R 向右移动,右侧无蚂蚁,不会与任何蚂蚁碰撞
    • 统计有效碰撞次数
      • 遍历裁剪后的区间 \([l, r]\)
        • dir[i] != 'S'(即 RL):ans++
      • 返回 ans
  4. 时间/空间复杂度

    • 时间复杂度:\(O(n)\),两次边界扫描 \(O(n)\),中间统计 \(O(n)\)
    • 空间复杂度:\(O(1)\),仅需常数额外空间
  5. 边界裁剪的核心思想

    • 无效蚂蚁识别:前缀 L 和后缀 R 是"逃逸蚂蚁",它们朝远离其他蚂蚁的方向移动,永远不会参与碰撞,可以直接排除
    • 有效区域性质:裁剪后的中间区域内,任何 R 右侧必然存在 LS,任何 L 左侧必然存在 RS,因此每个移动蚂蚁至少会发生一次碰撞
    • 碰撞规则统一:在有效区域内,每个非静止蚂蚁贡献恰好 \(1\) 次碰撞计数(相向碰撞被拆分为两只蚂蚁各贡献 \(1\),移动与静止碰撞也是 \(1\)),因此总次数等于有效区域内移动蚂蚁的数量
    • 贪心最优性:边界裁剪是确定性的,不存在遗漏或重复计算,每个有效区域内的移动蚂蚁必然且仅贡献一次碰撞
    • 适用于"一维相向运动 + 碰撞停止"类问题,边界逃逸分析可将复杂模拟转化为简单字符串处理

【算法标签】

字符串入门

【代码详解】

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

int cal(string s)
{
    int l = 0, r = s.size() - 1;  // 左右指针

    // 去掉前缀的'L'
    while (l <= r && s[l] == 'L')
    {
        l++;
    }
    // 去掉后缀的'R'
    while (l <= r && s[r] == 'R')
    {
        r--;
    }

    int ans = 0;
    // 统计中间非'S'字符的个数
    for (int i = l; i <= r; i++)
    {
        if (s[i] != 'S')
        {
            ans++;
        }
    }
    return ans;
}
int main()
{
    string dir;
    cin >> dir;  // 输入字符串
    cout << cal(dir);  // 输出计算结果
    return 0;
}

【运行结果】

RLRSLL
5
posted @ 2026-07-04 13:28  团爸讲算法  阅读(9)  评论(0)    收藏  举报