1 条题解
-
0
题意分析
题目背景
本题属于逆向搜索与路径验证问题,描述机器人Tom在网格场地中追逐Jerry幻象的过程。关键点在于根据模糊的移动记录,逆向推导所有可能的初始位置。
核心问题
- 场地建模:
- 的网格,
0
表示可通行,1
表示障碍物。
- 的网格,
- 移动规则:
- 每次移动为单一方向(上、下、左、右)。
- 移动步数记录为区间(如
1-2 R
表示向右移动1到2步)。
- 目标:
- 计算所有满足移动记录的初始位置数量。
输入输出
- 输入:
- 测试用例数。
- 每个测试用例包含:
- 网格行列数。
- 网格数据(的
0/1
矩阵)。 - 移动记录序列(步数区间+方向),以
0 0
结束。
- 输出:可能的初始位置数量。
解题思路
1. 逆向思维
- 从终点反推:假设Tom最终回到原点,逆向验证每条移动记录。
- 步数区间处理:将区间转换为步反向移动(如
1-2 R
变为向左移动1-2步)。
2. 深度优先搜索(DFS)
- 参数设计:
- :当前位置。
- :当前移动步数。
- :当前处理的移动记录索引。
- 终止条件:
- 处理完所有移动记录()。
- 递归逻辑:
- 若当前步数在区间内(),尝试处理下一条记录。
- 若可继续移动(),向反方向移动一步。
3. 可行性剪枝
- 边界检查:确保移动后仍在网格内。
- 障碍物检查:移动路径必须无障碍。
算法实现
代码框架
#include <bits/stdc++.h> using namespace std; typedef long long ll; int mp[110][110], n, m, T, num, ans; int dx[] = {0, 0, 1, -1}, dy[] = {-1, 1, 0, 0}; struct mmm { int le, mo, dir; } mv[1000]; bool dfs(int x, int y, int co, int step) { if (step == num) { return true; } if (co >= mv[step].le && co <= mv[step].mo) { if (dfs(x, y, 0, step + 1)) return true; } if (co < mv[step].mo) { int nx = x + dx[mv[step].dir], ny = y + dy[mv[step].dir]; if (nx >= 0 && nx < m && ny >= 0 && ny < n && mp[nx][ny] == 0) if (dfs(nx, ny, co + 1, step)) return true; } return false; } int main() { scanf("%d", &T); while (T--) { scanf("%d%d", &m, &n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { scanf("%d", &mp[i][j]); } } num = 0; while (scanf("%d%d", &mv[num].le, &mv[num].mo), mv[num].le || mv[num].mo) { char f; cin >> f; if (f == 'L') mv[num++].dir = 0; else if (f == 'R') mv[num++].dir = 1; else if (f == 'D') mv[num++].dir = 2; else if (f == 'U') mv[num++].dir = 3; } ans = 0; for (int i = 0; i < m; i++) for (int j = 0; j < n; j++) if (mp[i][j] == 0) if (dfs(i, j, 0, 0)) ans++; printf("%d\n", ans); } return 0; }
关键步骤
- 输入处理:读取网格和移动记录,存储方向为数字索引。
- DFS搜索:
- 从每个无障碍位置出发,逆向验证移动记录。
- 步数区间通过递归参数控制。
- 结果统计:统计所有满足条件的初始位置。
复杂度分析
- 时间:,其中为移动记录数,为最大步数。
- 空间:,存储网格和移动记录。
- 场地建模:
- 1
信息
- ID
- 72
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者