1 条题解

  • 0
    @ 2025-4-20 15:30:07

    题意分析

    题目背景

    本题属于逆向搜索与路径验证问题,描述机器人Tom在网格场地中追逐Jerry幻象的过程。关键点在于根据模糊的移动记录,逆向推导所有可能的初始位置。

    核心问题

    1. 场地建模
      • m×nm \times n的网格,0表示可通行,1表示障碍物。
    2. 移动规则
      • 每次移动为单一方向(上、下、左、右)。
      • 移动步数记录为区间[a,b][a,b](如1-2 R表示向右移动1到2步)。
    3. 目标
      • 计算所有满足移动记录的初始位置数量。

    输入输出

    • 输入
      • 测试用例数tt
      • 每个测试用例包含:
        • 网格行列数m,nm,n
        • 网格数据(m×nm \times n0/1矩阵)。
        • 移动记录序列(步数区间+方向),以0 0结束。
    • 输出:可能的初始位置数量。

    解题思路

    1. 逆向思维

    • 从终点反推:假设Tom最终回到原点,逆向验证每条移动记录。
    • 步数区间处理:将区间[a,b][a,b]转换为bb步反向移动(如1-2 R变为向左移动1-2步)。

    2. 深度优先搜索(DFS)

    1. 参数设计
      • (x,y)(x,y):当前位置。
      • coco:当前移动步数。
      • stepstep:当前处理的移动记录索引。
    2. 终止条件
      • 处理完所有移动记录(step=numstep = num)。
    3. 递归逻辑
      • 若当前步数在区间内(co[a,b]co \in [a,b]),尝试处理下一条记录。
      • 若可继续移动(co<bco < b),向反方向移动一步。

    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;
    }
    

    关键步骤

    1. 输入处理:读取网格和移动记录,存储方向为数字索引。
    2. DFS搜索
      • 从每个无障碍位置(i,j)(i,j)出发,逆向验证移动记录。
      • 步数区间通过递归参数stepssteps控制。
    3. 结果统计:统计所有满足条件的初始位置。

    复杂度分析

    • 时间O(tmnkbmax)O(t \cdot m \cdot n \cdot k \cdot b_{\text{max}}),其中kk为移动记录数,bmaxb_{\text{max}}为最大步数。
    • 空间O(mn)O(m \cdot n),存储网格和移动记录。
    • 1

    信息

    ID
    72
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者