#P3526. 第3题-叠叠高游戏
-
1000ms
Tried: 32
Accepted: 20
Difficulty: 4
所属公司 :
阿里
时间 :2025年8月31日-灵犀互娱
-
算法标签>栈
第3题-叠叠高游戏
解题思路
栈模拟
按目标从底到顶依次“定格”每个目标元素 x:
- 持续从预备区把积木
next扔到堆叠区(执行In),直到把x压入栈顶。 - 对于中间被压入的非目标数(
next != x),立刻执行一次Out丢弃,保证不会破坏已定格的下层结构。 - 当压入的正好是
x时,不再Out,保留在栈中,进入下一个目标。
完成全部目标后即可停止(无需处理余下的预备区积木)。
复杂度分析
- 时间复杂度:
O(n)(每个积木最多一次In与一次Out检查/操作)。 - 空间复杂度:
O(1)(除输出外只用常数变量;如不显式维护栈,直接构造操作序列即可)。
代码实现
Python
import sys
def solve():
data = list(map(int, sys.stdin.read().strip().split()))
if not data:
return
n, m = data[0], data[1]
target = data[2:2+m]
ops = []
nxt = 1 # 下一个将从预备区取出的编号
for x in target:
# 一直取到 x 为止
while nxt <= x:
ops.append("In")
if nxt != x:
ops.append("Out") # 中间数不是目标,立即丢弃
nxt += 1
# 现在栈顶保留了 x,不执行 Out
print(",".join(ops))
if __name__ == "__main__":
solve()
Java
import java.io.*;
import java.util.*;
public class Main {
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
List<Integer> all = new ArrayList<>();
String line;
// 读到所有整数
while ((line = br.readLine()) != null) {
line = line.trim();
if (line.isEmpty()) continue;
StringTokenizer st = new StringTokenizer(line);
while (st.hasMoreTokens()) all.add(Integer.parseInt(st.nextToken()));
}
if (all.size() < 2) return;
int n = all.get(0), m = all.get(1);
int[] target = new int[m];
for (int i = 0; i < m; i++) target[i] = all.get(2 + i);
StringBuilder ans = new StringBuilder();
int nxt = 1; // 将要 In 的编号
boolean first = true;
for (int x : target) {
while (nxt <= x) {
if (!first) ans.append(",");
ans.append("In");
first = false;
if (nxt != x) {
ans.append(",Out");
}
nxt++;
}
// 栈顶为 x,保留
}
System.out.println(ans.toString());
}
}
C++
#include <bits/stdc++.h>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
if (!(cin >> n >> m)) return 0;
vector<int> a(m);
for (int i = 0; i < m; ++i) cin >> a[i];
vector<string> ops;
int nxt = 1;
for (int x : a) {
while (nxt <= x) {
ops.push_back("In");
if (nxt != x) ops.push_back("Out");
++nxt;
}
// x 留在栈上
}
for (int i = 0; i < (int)ops.size(); ++i) {
if (i) cout << ",";
cout << ops[i];
}
cout << "\n";
return 0;
}
题目内容
有玩过叠叠高游戏么。
假设,预定给出一组积木,为其编号 list=[1,2,3,...,n] 。
游戏只有两种操作,所有的积木都是按顺序放在预备区。
积木可以放到预备区和堆叠区,在这两个区域里面,要必须先拿最上面的积木才能拿下面的积木。
第一种 In ,表示把积木从预备区拿到堆叠区。
第二种 Out ,表示把积木从堆叠区拿走并丢弃。
给定一个结束状态,求能通过 In 和 Out 的操作序列,得出该结束状态。
输入描述
输入第一行为 n 和 m ,表示积木的总数目和目标积木的数量;
输入第二行为 m 个数,为目标积木排列;
最多有 100 个积木。
输出描述
输出一行为操作序列,用 , 隔开输出保证合法。
样例1
输入
3 2
1 3
输出
In,In,Out,In
说明
读取数字 1 ,将 1 移到堆叠区中 [1]
读取数字 2 ,将 2 移到堆叠区中 [1,2] ,然后将其 Out ,现在堆叠区为 [1]
读取数字 3 ,将 3 移动堆叠区中 [1,3]
样例2
输入
3 3
1 2 3
输出
In,In,In
样例3
输入
4 2
1 2
输出
In,In
说明
放了 1 和 2 之后即可停止。