18276 走迷宫(传送门)
Description
有一个N*M的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,另外,在迷宫中
有一些传送门,走到传送门的入口即会自动被传送到传送门的出口(一次传送算1步)。人在迷宫中可以尝试
上下左右四个方向移动。现在给定一个迷宫和所有传送门的出入口,以及起点和终点,
问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。
输入格式
该程序为多CASE,第1行为CASE的数量
每一个CASE,第1行为两个数N(行)和M(列)
然后N行每行M个数
之后是一个数W,为传送门的数量
之后每行一个传送门的入口坐标c1(行),r1(列)和出口坐标c2,r2
之后是起点坐标和终点坐标sc(行) sr(列) ec(行) er(列)
注:传送门出入口和起点坐标和终点坐标不会出现在墙的位置
所有数字不超过100
输出格式
如题
输入样例
2
4 3
011
011
110
110
1
1 0 2 2
0 0 3 2
2 2
01
10
0
0 0 1 1
输出样例
3
die
思路:
走迷宫是金典bfs问题了,这里简单概述下。
在迷宫中的每一步起点now,我们有4个方向可以选择到达终点next,在4个方向中,我们需要选择不越界,不是墙,未走过的合法路径,作为我们下一次的起点now。我们使用一个队列来维护now和next的交替,直到队列为空,说明迷宫每一条路径全部遍历。每走一步,我们然step+1实现记录步数。
这道题只是在原有基础上做出了一点点改变,多出了第五个方向即传送门。当我们遇到传送门时,我们就无法选择四个方向。next就是传送门的出口。
我们把迷宫的最外一圈设为墙,将越界条件和墙的条件合并判断。
代码:
#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
int dex_x[4] = {-1,0,1,0};
int dex_y[4] = {0,1,0,-1};
char map[102][102];
struct node {
int x;
int y;
int step;
};
node door[102][102];
int main() {
ios::sync_with_stdio(false);
int T; cin >> T;
for (int i = 0; i < 102;i++) {
for (int j = 0; j < 102;j++) {
map[i][j] = '1';
}
}
for (int i = 0; i < T;i++) {
int N, M; cin >> N >> M;
for (int i = 1; i <= N;i++) {
for (int j = 1; j <= M;j++) {
cin >> map[i][j];
}
}
int w; cin >> w;
for (int i = 0; i < w;i++) {
node c1, c2;
cin >> c1.x >> c1.y >> c2.x >> c2.y;
++c1.x; ++c1.y; ++c2.x; ++c2.y;
door[c1.x][c1.y] = c2;
map[c1.x][c1.y] = '2';//传送们我们设为‘2’
}
int sc, sr, ec, er;
cin >> sc >> sr >> ec >> er;
++sc; ++sr; ++ec; ++er;
//初始化结束,
queue<node>q;
node start; start.x = sc; start.y = sr, start.step = 0;
q.push(start);
while (!q.empty()) {
node now, next;
now = q.front();
if (now.x == ec && now.y == er) { break; }//先判断,如果队首时终点则直接结束,保留队首。
q.pop();
if (map[now.x][now.y] == '2') {
next = door[now.x][now.y];
next.step = now.step + 1;
q.push(next);
map[now.x][now.y] = '1';
map[next.x][next.y] = '1';//标记已访问过
}
else {
for (int i = 0; i < 4;i++) {
next.x = now.x + dex_x[i];
next.y = now.y + dex_y[i];
if (map[next.x][next.y]!='1') {
next.step = now.step + 1;
q.push(next);
if(map[next.x][next.y]!='2')map[next.x][next.y] = '1';//除了传送门,标记已访问过
}
}
}
}
if (q.empty())cout << "die" << endl;//队空则说明未找到终点
else {
node end = q.front();
cout << end.step << endl;
}
}
}
18440 走迷宫(边界传送)
Description
有一个N*M(N,M<=10)的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,人在迷宫中可以尝试上下左右四个方向移动。 另外,在迷宫中如果从左边走出迷宫会回到迷宫最右边一格(只要该格不是墙),行不变,同样,从右边走出迷宫会 回到迷宫最左边一格,向上走出迷宫会回到迷宫最下边一格,向下走出迷宫会回到迷宫最上边一格。 现在给定一个迷宫,以及起点和终点,问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。
输入格式
该程序为多CASE,第1行为CASE的数量 每一个CASE,第1行为两个数N(行)和M(列) 然后N行每行M个数,之后是起点坐标和终点坐标sc(行) sr(列) ec(行) er(列)
输出格式
如题
输入样例
2 4 3 011 010 110 110 0 0 3 2 2 2 01 10 0 0 1 1
输出样例
4 die
思路:
这题和上一题差不多,在最基础的迷宫问题上做了一些变化。当next为边界时,next值会变化,变化规律也比较容易。实际上,每处理完一个case,应该再初始化map,只是不知道为什么就过了。
#include<iostream>
using namespace std;
#include<algorithm>
#include<queue>
int dex_x[4] = {-1,0,1,0};
int dex_y[4] = {0,1,0,-1};
char map[102][102];
struct node {
int x;
int y;
int step;
};
int main() {
ios::sync_with_stdio(false);
int T; cin >> T;
for (int i = 0; i < 102; i++) {
for (int j = 0; j < 102; j++) {
map[i][j] = '2';
}
}
for (int i = 0; i < T; i++) {
int N, M; cin >> N >> M;
for (int i = 1; i <= N; i++) {
for (int j = 1; j <= M; j++) {
cin >> map[i][j];
}
}
node start, end;
cin >> start.x >> start.y >> end.x >> end.y;
++start.x; ++start.y; ++end.x; ++end.y;
queue<node>q;
start.step = 0;
q.push(start);
while (!q.empty()) {
node now, next;
now = q.front();
if (now.x == end.x && now.y == end.y)break;
q.pop();
for (int i = 0; i < 4; i++) {
next.x = now.x + dex_x[i];
next.y = now.y + dex_y[i];
if (map[next.x][next.y] == '2') {//变换坐标
if (dex_x[i] == 0 && dex_y[i] == -1) { next.y = M; }
else if (dex_x[i] == 0 && dex_y[i] == 1) { next.y = 1; }
else if (dex_y[i] == 0 && dex_x[i] == 1) { next.x = 1; }
else { next.x = N; }
}
if (map[next.x][next.y]=='0') {
next.step = now.step + 1;
q.push(next);
map[next.x][next.y] = '1';
}
}
}
if (q.empty())cout << "die" << endl;
else cout << q.front().step << endl;
}
}