1 条题解
-
0
「ROI 2024 Day1」2026 题解
题目分析
题目要求模拟一个棋盘游戏,棋盘大小为 ,上面有带字母的棋子。给定一个由 组成的操作序列 ,每次操作将所有棋子向指定方向移动,直到遇到边界或其他棋子为止。最终输出所有操作后的棋盘状态。
数据范围:
- 所有数据组的 总和
- 所有数据组的 总和
算法思路
1. 操作序列优化
由于连续的同方向操作可以合并,代码首先对操作序列进行压缩:
- 相邻的相同方向操作只保留最后一次
- 对于水平/垂直方向的交替,如果出现循环模式可以进一步优化
2. 小规模情况直接模拟
当剩余操作数 时,直接调用相应的移动函数进行模拟。
3. 大规模情况使用置换环
对于更长的操作序列,发现操作具有周期性。通过预处理前几个操作建立位置映射关系,然后利用置换环理论批量处理剩余操作。
代码实现详解
坐标转换函数
int X(int u) { return (u - 1) / m + 1; } // 一维转二维行坐标 int Y(int u) { return u % m ? u % m : m; } // 一维转二维列坐标 int ID(int x, int y) { return (x - 1) * m + y; } // 二维转一维坐标四个方向的移动函数
每个函数都将该方向上的所有棋子向边界紧凑排列:
void Up(vector<int> *a) { FOR(j, 1, m) { int tmp(0); FOR(i, 1, n) if (~a[i][j]) { // ~(-1) = 0,判断非空 int num(a[i][j]); a[i][j] = -1, a[++tmp][j] = num; // 向上紧凑排列 } } } // Down、Left、Right 函数逻辑类似,只是遍历方向不同主处理函数
Cmain()1. 输入处理
I(n, m), t = n * m; FOR(i, 1, n) { scanf("%s", s + 1); a[i] = vector<int>(m + 1, -1); // -1 表示空格 FOR(j, 1, m) if (s[j] != '.') a[i][j] = s[j] - 'a'; // 字母转数字 0-25 }2. 操作序列压缩
auto typ = [&](char a) { return a == 'L' || a == 'R'; }; // 判断水平方向 FOR(i, 1, tmp) { char c(s[i]); while (Q && typ(s[Q]) == typ(c)) --Q; // 合并连续同方向操作 if (Q < 2 || s[Q - 1] != c) s[++Q] = c; // 避免 LRLR 重复模式 }3. 小规模直接模拟
if (Q <= 8) { FOR(i, 1, Q) s[i] == 'L' ? Left(a) : ... // 根据方向调用相应函数 return Output(a); }4. 大规模情况预处理
tmp = 4 + Q % 4; // 先处理前几个操作 FOR(i, 1, tmp) ... // 执行前 tmp 个操作 Q -= tmp; FOR(i, 1, Q) s[i] = s[i + tmp]; // 调整剩余操作序列 // 建立位置索引 FOR(i, 1, n) FOR(j, 1, m) if (~a[i][j]) idx[i][j] = ID(i, j); // 执行 4 个操作建立映射关系 FOR(i, 1, 4) ... // 构建父节点关系(置换映射) FOR(i, 1, n) FOR(j, 1, m) if (~idx[i][j]) fa[idx[i][j]] = ID(i, j);5. 置换环处理
FOR(i, 1, n) FOR(j, 1, m) if (~a[i][j] && !vis[ID(i, j)]) { const int u(ID(i, j)); vector<int> tmp {u}; // 寻找整个置换环 for (int v(fa[u]); v && v != u; v = fa[v]) tmp.push_back(v), vis[v] = true; // 计算最终位置:Q % 环长 的偏移 int y(Q % tmp.size()); for (int x : tmp) b[X(tmp[y])][Y(tmp[y])] = a[X(x)][Y(x)], y = (y + 1) % tmp.size(); }复杂度分析
- 时间复杂度:,其中 是操作序列长度
- 空间复杂度:
算法亮点
- 操作序列压缩:减少不必要的重复操作
- 置换环技术:将多次重复操作转化为环上的偏移计算
- 坐标映射:使用一维索引简化位置关系处理
- 分治策略:小规模直接模拟,大规模使用数学优化
这种方法充分利用了操作序列的周期性和置换性质,将看似复杂的多次移动转化为高效的数学计算,成功解决了大数据量下的性能问题。
- 1
信息
- ID
- 4761
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者