洛谷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)$ 将被摆上路障。
输出格式
对于每一组数据,输出 Yes 或 No,回答 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;
}

浙公网安备 33010602011771号