洛谷P3395 路障 题解

题目如下# P3395 路障

题目描述

B 君站在一个 $n\times n$ 的棋盘上。最开始,B君站在 $(1,1)$ 这个点,他要走到 $(n,n)$ 这个点。

B 君每秒可以向上下左右的某个方向移动一格,但是很不妙,C 君打算阻止 B 君的计划。

每秒结束的时刻,C 君 会在 $(x,y)$ 上摆一个路障。B 君不能走在路障上。

B 君拿到了 C 君准备在哪些点放置路障。所以现在你需要判断,B 君能否成功走到 $(n,n)$。

保证数据足够弱:也就是说,无需考虑“走到某处然后被一个路障砸死”的情况,因为答案不会出现此类情况。

输入格式

首先是一个正整数 $T$,表示数据组数。

对于每一组数据:

第一行,一个正整数 $n$。

接下来 $2n-2$ 行,每行两个正整数 $x$ 和 $y$,意义是在那一秒结束后,$(x,y)$ 将被摆上路障。

输出格式

对于每一组数据,输出 YesNo,回答 B 君能否走到 $(n,n)$。

输入输出样例 #1

输入 #1

2

2
1 1
2 2

5
3 3
3 2
3 1
1 2
1 3
1 4
1 5
2 2

输出 #1

Yes
Yes

说明/提示

样例解释:

以下 0 表示能走,x 表示不能走,B 表示 B 君现在的位置。从左往右表示时间。

Case 1:
0 0    0 0    0 B  (已经走到了)
B 0    x B    x 0
Case 2:
0 0 0 0 0    0 0 0 0 0    0 0 0 0 0    0 0 0 0 0
0 0 0 0 0    0 0 0 0 0    0 0 0 0 0    0 0 0 0 0
0 0 0 0 0    0 0 x 0 0    0 0 x 0 0    0 0 x 0 0
0 0 0 0 0    0 0 0 0 0    0 0 x 0 0    0 0 x 0 0
B 0 0 0 0    0 B 0 0 0    0 0 B 0 0    0 0 x B 0 ......(B君可以走到终点)

题目分析
这个和之前写过的一个基本相似,路障就相当于迷宫的墙壁,而且这个不用记录路径,只需哟啊判断是否到达终点

要注意是每走一步设置一个路障

解:
首先还是定义一下结构体
typedef struct { int x, y, step; } Node;

初始化两个数组
int visited[MAXN][MAXN]; int obstacle[MAXN][MAXN];

重点在这里
if (nx >= 1 && nx <= n && ny >= 1 && ny <= n && !visited[nx][ny] && (obstacle[nx][ny] == 0 || obstacle[nx][ny] > next)) { //从上到下分别是 1.防止超出 2.确认没有被访问 3.确认下一步不是路障 queue[rear++] = (Node){nx, ny, next}; visited[nx][ny] = 1; }
这三点规定了我们能走的路径

这一条写在主函数里
for (int t = 1; t <= 2 * n - 2; t++) { //从第二步开始放路障,走第一步时还没有路障 int a, b; scanf("%d %d", &a, &b); obstacle[a][b] = t; }
表明我们放路障的位置和上面的呼应

好了完整代码如下
`

点击查看代码
#include <stdio.h>
#include <string.h>
#include <algorithm>

#define MAXN 10001

typedef struct {
    int x, y, step;
} Node;

int n;
int visited[MAXN][MAXN];
int obstacle[MAXN][MAXN];

int dx[4] = {0, 0, -1, 1};  // 上下左右移动
int dy[4] = {-1, 1, 0, 0};

bool BFS() {
    Node queue[MAXN * MAXN];
    int front = 0, rear = 0;

    memset(visited, 0, sizeof(visited));

    queue[rear++] = (Node){1, 1, 0};
    visited[1][1] = 1;

    while (front < rear) {
        Node now = queue[front++];

        if (now.x == n && now.y == n) {
            return true;
        } //到达终点了

        for (int i = 0; i < 4; i++) {
            int nx = now.x + dx[i];
            int ny = now.y + dy[i];
            int next = now.step + 1;

            if (nx >= 1 && nx <= n && ny >= 1 && ny <= n
            && !visited[nx][ny]
            && (obstacle[nx][ny] == 0 || obstacle[nx][ny] > next)) {
                //从上到下分别是 1.防止超出 2.确认没有被访问 3.确认下一步不是路障
                queue[rear++] = (Node){nx, ny, next};
                visited[nx][ny] = 1;
            }
        }
    }
    return false;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);

        if (n == 1) {
            printf("Yes\n");
            continue; //1 * 1 格子
        }

        memset(obstacle, 0, sizeof(obstacle));
        for (int t = 1; t <= 2 * n - 2; t++) { //从第二步开始放路障,走第一步时还没有路障
            int a, b;
            scanf("%d %d", &a, &b);
            obstacle[a][b] = t;
        }

        if (BFS()) {
            printf("Yes\n");
        } else {
            printf("No\n");
        }
    }
    return 0;
}
`
posted @ 2025-05-07 00:57  sirro1uta  阅读(39)  评论(0)    收藏  举报