简单搜索&&进阶搜索 - Virtual Judge (vjudge.net)
【题目描述】
fish被关在一个两层的迷宫里,迷宫的入口是S(0,0,0),fish的位置用P表示,时空传输机用# 表示,墙用*表示,平地用.表示。勇者们一进入时空传输机就会被转到另一层的相对位置,但如果被转到的位置是墙的话,那勇者们就会被撞死。勇者们在一层中只能前后左右移动,每移动一格花1时刻。层间的移动只能通过时空传输机,且不需要任何时间。
【输入】
输入的第一行C表示共有C个测试数据,每个测试数据的前一行有三个整数N,M,T。 N,M迷宫的大小N* M(1 <= N,M <=10) 。T如上所意。接下去的前N* M表示迷宫的第一层的布置情况,后N* M表示迷宫第二层的布置情况。
【输出】
如果勇者们能够在T时刻能找到fish就输出“YES”,否则输出“NO”。
解题思路
这个题写了好久,刚开始用的 dfs 写的,我以为是效率很低所以过不了,但是后面改成 bfs 还是没过,主要是有条件没判断:从一层传到另一层时,此时不能为‘ * ’,传到的地方是墙肯定不行,而且不能是‘ # ’,如果到达的地方也是传送门的话,就是个循环,出不来了,这个情况也要考虑。
这个题是在原本的搜索上加上了传送门,所以在遍历的时候也是定义应该二维 dir 的方向数组,分别代表 x 轴和 y 轴的方向。
我是用 a[tz][ty][tx] 记录的地图,其中 tz 是层数,ty 是行数,tx 是列数。
用 book 数组记录该点是否走到,然后遇到传送门‘ # ’,就更改 tz 的值,并且判断另外一层是否能到:
我是用一个三维数组存放地图,在走到传送门 ‘#’ 时,将地图的层数改变,并且将
if (a[tz][ty][tx] == '#')
{
tz = tz ? 0 : 1;
if (a[tz][ty][tx] == '*'||a[tz][ty][tx]=='#')
continue;
}
代码:
#include<stdio.h>
#include<string.h>
int time, n, m;
char a[15][15][15];
int book[15][15][15];
struct node
{
int x;//列数
int y;//行数
int z;//层数
int t;//步数
};
struct node k[10000];
int main()
{
int t, i, j;
scanf("%d", &t);
while (t--)
{
int flag = 0;
scanf("%d%d%d", &n, &m, &time);
for (i = 0; i < n; i++)
scanf("%s", a[0][i]);
for (i = 0; i < n; i++)
scanf("%s", a[1][i]);
int head = 0, tail = 0;
int dir[4][2] = { 0,1,0,-1,1,0,-1,0 };
k[tail].x = 0;
k[tail].y = 0;
k[tail].z = 0;
k[tail].t = 1;
book[0][0][0] = 1;
tail++;
while (head < tail)
{
for (i = 0; i < 4; i++)
{
int tx = k[head].x + dir[i][0];
int ty = k[head].y + dir[i][1];
int tz = k[head].z;
if (tx < 0 || tx >= m || ty < 0 || ty >= n)//超出地图的范围就去掉这种情况
continue;
if (book[tz][ty][tx] == 0 && a[tz][ty][tx] != '*')//没到墙壁‘*’,就接着判断是否可以加入队列
{
book[tz][ty][tx] = 1;//先把该点标记
if (a[tz][ty][tx] == '#')//传送门
{
tz = tz ? 0 : 1;
if (a[tz][ty][tx] == '*'||a[tz][ty][tx]=='#')//这种情况也要考虑
continue;
}
book[tz][ty][tx] = 1;//接着把通过传送门的地图也标记,防止重复查找
k[tail].x = tx;
k[tail].y = ty;
k[tail].z = tz;
k[tail].t = k[head].t + 1;//加入队列
tail++;
}
if (a[tz][ty][tx] == 'P')//达到终点的情况
{
flag = 1;//设置一个标记,在bfs中若是找到终点,此时一定是最短步数的情况之一
if (k[head].t <= time)//如果该点不满足条件,说明不能在规定时间找到终点
flag = 2;
break;
}
}
if (flag == 1||flag==2)
break;
head++;
}
if (flag == 2)
printf("YES\n");
else
printf("NO\n");
memset(book, 0, sizeof(book));//循环输出,要把book数组里的值初始化
}
return 0;
}