Problem Description
张晨乐在一个古老的迷宫中发现了一个手机,这个手机深深地吸引了他。
然而,当他拾起手机,迷宫开始摇晃,张晨乐能感觉到地面下沉。他意识到:这个手机只是一个诱饵!于是,他不顾一切地试图冲出这个迷宫。
迷宫是一个大小为N*M的矩形,有一扇门,一开始,门是关闭的,并在第T秒打开一瞬间(小于1秒的时间)。因此,张晨乐必须刚好在第T秒钟到达门口。
每一秒,他都可以向上,下,左,右四个相邻的位置中的任意一个移动。一旦他进入一个新的地方,这个地方的地面就会开始下沉,并在下一秒消失。因此,他不能在一个地方停留超过一秒钟,也不能再进入曾经走过的地方。
请问,可怜的张晨乐能够逃出迷宫吗?
Input
输入由多个测试用例组成。
每个测试用例的第一行包含三个整数N,M和T(1 <N,M <7; 0 <T <50),分别表示迷宫的大小和门打开的时间。
接下来的N行给出迷宫布局,每行包含M个字符。
每个字符含义如下:
‘X’:不能进入的墙
‘S’:起点
‘D’:门
‘.’:可以行走的地方
输入以三个0结束,这个测试用例不被处理。
Output
对于每组测试数据,如果张晨乐能够逃出迷宫,则请输出“YES”,否则,请输出“NO”。每组数据输出占一行。
Sample Input
4 4 5
S.X.
…X.
…XD
…
3 4 5
S.X.
…X.
…D
0 0 0
Sample Output
NO
YES
初始状态: 起点位置(st_x, st_y)
目标状态: time = T时到达终点位置(ed_x, ed_y)
根据题目规则,即移动方式进行状态转移r[4][2] = {
{1, 0}, {-1, 0}, {0, 1}, {0, -1}}
不使用bfs原因:
bfs倾向于解决"最小问题",比如最短的次数,最短的时间等
而本题需要恰好在某个时间到达,如果使用bfs并且在最终判断结果上加上step == t,
在得到所有可能的过程中,可能某个状态需要后面出现才能到达,但是由于“剪枝”效果,改状态在之前出现后会被标记,不能够在后面出现。
若去掉"剪枝"那么可能会出现死循环。
1)奇偶性剪枝
可以将地图看作内容为0和1的地图,如5*5地图
(行号 + 列号)为偶数,则为0;为基数,则为1;
从图中可以看出,想从值为1的点到达值为1的点,必须走偶数次,即
1 -> 1 : 偶数
1 -> 0 : 奇数
0 -> 1 : 奇数
0 -> 0 : 偶数
所以可以通过(起点坐标0/1) -> (终点坐标0/1):t是否满足得到的结果的奇偶
2) 所有格子数-墙数 <= 时间
取等问题,因为起点位置占了一个格子所以需要取等
例如:33,起点为(1, 1), 终点为(3, 3) t = 9;
这里 33 - 0 <= 9 不能够到达
#include<bits/stdc++.h>
using namespace std;
// n:行, m:列, t:开门时间,flag标记是否能成功逃出,wall: 墙的数量,st:起始坐标,ed终点坐标
int n, m, t, flag, wall, st_x, st_y, ed_x, ed_y;
// vis标记是否访问过, r: 移动的方式
int vis[9][9], r[4][2] = {
{
1, 0}