车厢调度(train)

GitHub跳转原题关系图返回列表

车站 C 是栈,目标是 1..n 的栈混洗:对每个出站车厢把更小编号的未出站车厢全部入栈,检查栈顶恰好匹配,单遍贪心模拟 O(n) 判定。

OJ: roj

题目 ID: 1357

难度:入门

标签:栈模拟贪心

创建: 2026-09-30 06:49

更新: 2026-10-05 11:52

题目描述

nn 节车厢按 1,2,…,n1,2,\dots,n 顺序从 A 驶入,经车站 C(栈)驶向 B。判断能否以给定顺序 a1,…,ana_1,\dots,a_n 出站。n≤1000n \le 1000。

思路

车站 C 是栈。要让 aia_i 出站,所有编号 ≤ai\le a_i 且尚未出站的车厢必须先入栈。维护 cur(下一节未入栈车厢)和栈,对每个目标 aia_i:若 ai≥cura_i \ge cur 则把 cur..aicur..a_i 入栈;然后弹出栈顶,若栈顶不是 aia_i 则无解。全部成功输出 YES。

参考代码

Python 版:

python
#!/usr/bin/env python3
# Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
# rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
# rainboy的学习导航网站: https://idx.roj.ac.cn
# create_at: 2026-10-01 10:30
# update_at: 2026-10-01 10:30

import sys


def solvable(a: list[int]) -> bool:
    """目标出站序列能否由 1..n 依次入站(车站 C 是栈)得到。"""
    stack: list[int] = []       # 车站 C:栈底是先入站的车厢
    cur = 1                     # 下一节还没进站的车厢编号
    for x in a:
        # 编号不超过 x 的车厢依次入栈;x < cur 时没有新车厢可入,cur 也不能回退
        if x >= cur:
            stack += range(cur, x + 1)
            cur = x + 1
        if not stack or stack.pop() != x:  # x 必须恰好是栈顶才能出站
            return False
    return True


def solve() -> None:
    data = iter(map(int, sys.stdin.buffer.read().split()))
    n = next(data)
    a = [next(data) for _ in range(n)]
    print("YES" if solvable(a) else "NO")


if __name__ == "__main__":
    solve()

C++ 版(同一算法):

cpp
/**
 * Author by Rainboy blog: https://rainboylv.com github: https://github.com/rainboylvx
 * rbook: -> https://rbook.roj.ac.cn  https://rbook2.roj.ac.cn
 * rainboy的学习导航网站: https://idx.roj.ac.cn
 * create_at: 2026-10-05 11:52
 * update_at: 2026-10-05 11:52
 */
#include <iostream>
using namespace std;

typedef long long ll;

const int MAXN = 1005;

int n;
int a[MAXN];
int stk[MAXN]; // 车站 C 模拟栈,stk[top] 为栈顶
int top;       // 栈顶指针,0 表示空栈

bool solvable() {
    int cur = 1; // 下一节还没进站的车厢编号
    for (int i = 1; i <= n; ++i) {
        int x = a[i];
        // 把 cur..x 依次入栈;x < cur 时无需入栈
        if (x >= cur) {
            for (int v = cur; v <= x; ++v) {
                stk[++top] = v;
            }
            cur = x + 1;
        }
        // 检查栈顶是否恰好为 x
        if (top == 0 || stk[top] != x) {
            return false;
        }
        --top; // 弹出 x
    }
    return true;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    if (!(cin >> n)) return 0;
    for (int i = 1; i <= n; ++i) {
        cin >> a[i];
    }

    cout << (solvable() ? "YES" : "NO") << "\n";
    return 0;
}