针对迷宫问题,用到的技巧是不断出入队列,把队头元素弹出队列后,将转移得到的状态再放入队中,这样做到的是BFS的广度优先搜索,等于每次找到的都是离原点最近的状态,所以肯定最终得到的是最短路径。
在开始阶段有一部分初始化,
#include <queue>
#define INF 10005//到各点距离的最大值
#define MAXN 205//迷宫大小
struct node
{
int x,int y;
node(int a,int b)
{
x = a;y = b;
}
node(){} //这里可以说是这个结构体中最关键的一步,使用了面向对象程序设计的技巧 空构造方法
};
node s,t;//记录起始坐标以及终点坐标
之后是全局变量区域
char maze[MAXN][MAXN];//存储迷宫字符串
int d[MAXN][MAXN];//到各点的距离
queue <node> que;//结构体类型的队列
int n,m;
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
之后部分以最近所做的寻找键盘为例1,以SJY学长的四维迷宫作为例2来理解迷宫问题
例1 BJUTACM OPENJUDGE
183G:电脑键盘是否存在
-
总时间限制:
- 1000ms 内存限制:
- 100000kB
-
描述
-
奇奇小朋友是一位哲学家,她是程序员希希的鼓励师。
希希每天回家以后都要工作到很晚,没有时间陪奇奇。
奇奇很想让希希多陪陪她,所以这一天,奇奇把家里的键盘藏了起来,这样希希回家以后就不能写代码了。
希希回家以后发现键盘不见了,他问奇奇键盘去哪儿了,奇奇说:
「也许键盘不见了,你就认识到键盘不存在了;
也许是你认识到你应该多陪陪我了,所以键盘它就自己消失了」
聪明的你,请帮助因为失去了键盘而没有办法编程的希希找回他的键盘。
键盘被藏在房间里了,房间里有且仅有一柄键盘,但还有一些其他的物品。
房间里的空地可供通行,而放有物品的地方则不能通行。
你只能从入口进入房间,入口有且仅有一个。
在房间内的空地上你只能向前、后、左、右四个方向通行。
输入
-
第一行是一个整数 T,表示以下会有 T 个测试用例。
每个测试用例第一行有两个整数,R 和 C,
分别代表房间的长和宽。(1 <= R, C <= 200)
接下来是 R 行,每行 C 个字符,代表整个房间。
键盘用字符 'K' 表示,房间内的其他物品用字符 '#' 表示,空地用字符 'O' 表示。
房间的入口用 'I' 表示。
输出
-
对于每个测试用例:
如果你进入房间后成功找到了键盘,请输出一行形如 "Are you OK?"(不包含双引号)的字符串询问希希现在还好吗,根据你找到键盘所用的最少步数 n 将字符串中的 'O' 重复 n+1 遍;
如果你进入房间后无法找到键盘,请输出 "I have already eaten the keyboard." (不包含双引号)告诉希希键盘被你偷偷吃掉了。
样例输入
-
3 5 5 IO### #O### #OO## ##OO# ###OK 5 5 K#OOO O#O#O O#I#O O###O OOOOO 3 3 I#O ##O OOK
样例输出
-
Are you OOOOOOOOK? Are you OOOOOOOOOOOOOOOK? I have already eaten the keyboard.
代码
#include <iostream>
#include <algorithm>
#include <stack>
#include <queue>
#include <vector>
#include <cstring>
#include <cmath>
#include <cstdlib>
#define INF 100005
#define MAXN 500
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
struct node {
int x,y;
node(int a,int b)
{
x = a;
y = b;
}
node(){}
};
node s,t;
char maze[MAXN][MAXN];
int d[MAXN][MAXN];
queue <node> que;
int n,m;
int dx[4] = {1,0,-1,0};
int dy[4] = {0,1,0,-1};
int bfs()
{
que.push(s);
d[s.x][s.y] = 1;
while(que.size()!=0)
{
node temp = que.front();
que.pop();
if(temp.x==t.x&&temp.y==t.y) return d[t.x][t.y];
for(int i=0;i<4;i++)
{
int nx = temp.x + dx[i];
int ny = temp.y + dy[i];
if(nx>=0&&nx<n&&ny>=0&&ny<m&&maze[nx][ny]!='#'&&d[nx][ny]==INF)
{
d[nx][ny] = d[temp.x][temp.y] + 1;
que.push(node(nx,ny));
}
}
}
return d[t.x][t.y];
}
int main(int argc, char** argv) {
int p;
scanf("%d",&p);
for(int k=0;k<p;k++)
{
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
scanf("%s",maze[i]);
}
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
d[i][j] = INF;//初始化所有点距离为无穷大
if(maze[i][j]=='I') s = node(i,j);
else if(maze[i][j]=='K') t = node(i,j);
}
}
if(bfs()==INF)
{
printf("I have already eaten the keyboard.\n");
}
else
{
printf("Are you ");
for(int i=0;i<bfs()-1;i++)
{
printf("O");
}
printf("K?\n");
}
}
//system("pause");
return 0;
}
例2 四维迷宫问题
分析:针对于四维迷宫,主要是多个方向的遍历更加困难 而且不能使用pair 必须使用结构体
lq17E:今
-
总时间限制:
- 1000ms 内存限制:
- 256000kB
-
描述
-
20 年前的今天,曾经发生过一件轰动全球的大事。生活在四维空间中的三体人为了入侵地球,将地球空间的维度升到了四维,并设置了重重障碍,阻碍地球人联络增援。在全球人民的共同努力之下,地球人侥幸逃出了三体人布下的四维天罗地网,拯救了地球。但是出于安抚民心的需要,世界各国联合起来,共同抹去了这场星球之战的一切痕迹。现在,一名在那场战役用幸存的士兵找到了你,希望你重现当年的场景,挽回救球英雄们的尊严!
输入
-
第一行为四个整数,n, m, p, q (1 ≤ n, m, p, q ≤ 20)。
接下来的数据分为 n 组输入,每组有 m 个 p × q 字符矩阵,表示四维空间的最后三个维度。n 组输入共同表示整个四维迷宫。
迷宫中的字符有四种可能,为「.」、「#」、「S」和「T」,分别表示通道,障碍,起点和终点。其中起点和终点有且只有一对。每一步可以向相邻的 8 个方向的通道(或起点和终点)移动。
输入保证存在从起点到终点的路径。
输出
- 输出从起点到终点的最短路径的长度 样例输入
-
2 2 2 2 S. ## #. ## ## T# #. ..
-
样例输出
-
6
-
这段代码由于是早期所写,可能BUG 以及无用的部分很多#include <iostream> #include <queue> #define INF 10005 using namespace std; char maze[20][20][20][20]; int color[20][20][20][20] = {0};//0代表没有访问过 1代表访问过 int dd[20][20][20][20]; int uu[8] = {-1, 1, 0, 0, 0, 0, 0, 0}, vv[8] = {0, 0, -1, 1, 0, 0, 0, 0}, ww[8] = {0, 0, 0, 0, -1, 1, 0, 0}, zz[8] = {0, 0, 0, 0, 0, 0, -1, 1}; int n,m,p,q; int sx,sy,sz,st; struct chucun//封装了四个坐标 { int x; int y; int z; int t; chucun(int a, int b, int c, int d){ x = a; y = b; z = c; t = d; } chucun(){} }; chucun s,t; int tx,ty,tz,tt; int flags = 1; int flagt = 1; bool judge(int w, int x, int y, int z){ if (dd[w][x][y][z] != INF || w < 0 || w >= n || x < 0 || x >= m || y < 0 || y >= p || z < 0 || z >=q || maze[w][x][y][z] == '#') return 0; return 1; } int bfs() { queue<chucun>que; que.push(s); dd[s.x][s.y][s.z][s.t] = 0; // printf("%d\t%d\t%d\t%d\n",s.x,s.y,s.z,s.t); while(que.size()) { chucun temp = que.front(); // printf("&&&&&&&&&\n"); que.pop(); // printf("#########\n"); if(temp.x==t.x&&temp.y==t.y&&temp.z==t.z&&temp.t==t.t) break; for(int i=0;i<8;i++) { int nx = temp.x + uu[i]; int ny = temp.y + vv[i]; int nz = temp.z + ww[i]; int nt = temp.t + zz[i]; // printf("nx = %d\tny = %d\tnz = %d\tnt = %d\n",nx,ny,nz,nt); // if(nx>=0&&nx<n&&ny>=0&&ny<m&&nz>=0&&nz<p&&nt>=0&&nt<q&&maze[nx][ny][nz][nt]!='#'&&dd[nx][ny][nz][nt]==INF) if(judge(nx,ny,nz,nt)) { // printf("nx = %d\tny = %d\tnz = %d\tnt = %d\n",nx,ny,nz,nt); dd[nx][ny][nz][nt] = dd[temp.x][temp.y][temp.z][temp.t]+1; // printf("%d\t%d\t%d\t%d\n",qqq.x,qqq.y,qqq.z,qqq.t); que.push(chucun(nx,ny,nz,nt)); //temp } } } return dd[t.x][t.y][t.z][t.t]; } int main(void) { char temp; char temp2; int count = 0; scanf("%d%d%d%d",&n,&m,&p,&q); for(int i=0;i<n;i++) { for(int j=0;j<m;j++) { for(int k=0;k<p;k++) { for(int l=0;l<q;l++) { do { scanf("%c",&temp); if(temp=='#'||temp=='S'||temp=='T'||temp=='.') { temp2 = temp; break; } }while(1); maze[i][j][k][l] = temp2; dd[i][j][k][l] = INF; if(temp2=='S') { s = chucun(i,j,k,l); // flags = 0; } if(temp2=='T') { t = chucun(i,j,k,l); // flagt = 0;//printf("###%d\t%d\t%d\t%d\n",tx,ty,tz,tt); } if(count==n*m*q*p) goto a; } } } } a: // for(int i=0;i<n;i++) // for(int j=0;j<m;j++) // for(int k=0;k<p;k++) // for(int l=0;l<q;l++) // printf("%c",maze[i][j][k][l]); // printf("%d",bfs()); return 0; }