1.题目描述:
Salvation
时间限制:
1000 ms | 内存限制:
65535 KB
难度:
3
-
描述
-
神秘瀑布镇是一个神秘的地方,那里有吸血鬼,狼人,巫师,二重身。 Klaus(吸血鬼祖先) 为了利用 Elena 的血液发展他的混血大军(吸血鬼&狼人),也来到了神秘瀑布镇。Stefan 因为深爱着 Elena ,于是 Stefan 决定去唤醒吸血鬼猎人,来解救 Elena 。
吸血鬼猎人被封锁在一个迷宫里,这个迷宫有一种特性,只要进入就会失去方向感。于是 Stefan 想到一种方法,以左为标准(即优先左走),其次向前,向右,如果都无法走就向后走(即向右转两次)。他可以向上下左右四个方向的空格移动一个格,每次耗费1分钟。Stefan 在得知你是一个有天赋的程序员后,决定让你判断他是否能找到吸血鬼猎人。
-
输入
-
输入包含多组测试数据,第一行输入 n , m ( 2 < n ,m <= 100) ,接下来n行每行m个字符,第 n + 2 行一个字符表示初始方向(E W S N)。
“.”代表空格 ,“#”代表墙 , “ T ”代表初始位置,“X”代表吸血鬼猎人的位置。
输出
- 输出一行,如果能找到输出“YES”,否则输出“NO”。 样例输入
-
4 4 .... .##. .##. TX.. N 4 4 .... .##. .### T#.X N
样例输出
-
YES NO
提示
- 优先左走即:如果左边能走就向左走,如果不能走向前走,如果前不能走,向右走,如果右不能走向后走。
-
输入包含多组测试数据,第一行输入 n , m ( 2 < n ,m <= 100) ,接下来n行每行m个字符,第 n + 2 行一个字符表示初始方向(E W S N)。
2.算法思想:
首先本体很明显需要用到DFS来查找可行解,但是本体新颖之处有两个
1.变方向
2.顺路径搜索
我们先来看看顺路径搜索的策略:
首先,根据我们以往的DFS的经验来看,我们想要查找可行解的话,需要的是将整个图进行遍历,用深搜的话是O(n*2)的时间复杂度,但是本体的特殊性在于我们是有方向优先的,所以说,我们不能按照以往的思维习惯来在每个点的基础上搜四个方向
相反,我们应该按照我们平常找路的思路来
其实我们平常找路的思路和标准的DFS的回溯思想还好i有着不一样的地方的
在理清题意之前,我们首先需要搞明白两者之间的不同之处
回溯的思想:利用递归,我们每次的四个方向查找失败之后,都会回溯至父点处重新进行下一轮选择
本题的思路:因为本题中声明了我们的搜索方式是按照左-前-右-后的思路来进行查找,所以说,加入我们走进了死胡同,三个方向都查找失败,但是轮到我们要往回走,往回走的时候,方向就改变了,在回溯法的思想中,我们遇到死胡同之后,因为向后的方向已经被标记过走过,所以说,我们是直接回溯至源点做下一轮选择,这两点是不一样的
就跟本来说,其实我们只要将平常的DFS的搜索时不要进行标记,允许我们向后走原路的话,也可以轻而易举结局这个小的问题
其次,变方向,照理来说,变方向是非常的复杂的,我开始的思路是开辟四种选择策略,针对不同的方向选择不同的选择策略,但是发现没有领悟精髓
大神的公式键值精简到世界崩塌,还没有搞懂原理,但是参考一下吧
3.AC代码
1.大神的简化代码:
#include"iostream"
#include"cstdio"
#include"cstring"
#include"cstdlib"
#define N 120
using namespace std;
int nx[4]={-1,0,1,0};
int ny[4]={0,-1,0,1};
int n,m;
int book[N][N];
char map[N][N];
int bx,by;
int j;
char d;
int ds;
void dfs(int x,int y,int p)
{
if(j) return ;
for(int i=1;i>-3;i--)
{
int k=(p+i+8)%4;
int dx=x+nx[k];
int dy=y+ny[k];
if(dx<1||dy<1||dx>n||dy>m||map[dx][dy]=='#') continue;
else
{
if(map[dx][dy]=='X')
{
j=1;
return ;
}
else
{
if(book[dx][dy]==4) return ;
book[dx][dy]++;
dfs(dx,dy,k);
return ;
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
j=0;
memset(book,0,sizeof(book));
memset(map,0,sizeof(map));
getchar();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='T')
{
bx=i;
by=j;
}
}
getchar();
}
scanf("%c",&d);getchar();
if(d=='N') ds=0;
else if(d=='W') ds=1;
else if(d=='S') ds=2;
else ds=3;
dfs(bx,by,ds);
if(j) printf("YES\n");
else printf("NO\n");
}
return 0;
}
2.我的思路:
#include"iostream"
#include"cstdio"
#include"cstring"
#include"cstdlib"
using namespace std;
int n,m;
int nn[4][2]={{0,-1},{-1,0},{0,1},{1,0}};
int ns[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
int nw[4][2]={{1,0},{0,-1},{-1,0},{0,1}};
int ne[4][2]={{-1,0},{0,1},{1,0},{0,-1}};
char map[200][200];
int book[200][200];
char dir;
int bx,by;
int ex,ey;
bool dfs(int x,int y,char d)
{
if(d=='N')
{
int dx,dy;
for(int i=0;i<4;i++)
{
dx=x+nn[i][0];
dy=y+nn[i][1];
if(book[dx][dy]==4) return false;
if(dx==ex&&dy==ey) return true;
book[dx][dy]++;
if(dx<1||dy<1||dx>n||dy>m||map[dx][dy]=='#') continue;
else
{
bool k;
switch(i)
{
case 0:k=dfs(dx,dy,'W');break;
case 1:k=dfs(dx,dy,'N');break;
case 2:k=dfs(dx,dy,'E');break;
case 3:k=dfs(dx,dy,'S');break;
}
if(k==true) return true;
else return false;
}
}
}
else if(d=='S')
{
int dx,dy;
for(int i=0;i<4;i++)
{
dx=x+ns[i][0];
dy=y+ns[i][1];
if(book[dx][dy]==4) return false;
if(dx==ex&&dy==ey) return true;
book[dx][dy]++;
if(dx<1||dy<1||dx>n||dy>m||map[dx][dy]=='#') continue;
else
{
bool k;
switch(i)
{
case 0:k=dfs(dx,dy,'E');break;
case 1:k=dfs(dx,dy,'S');break;
case 2:k=dfs(dx,dy,'W');break;
case 3:k=dfs(dx,dy,'N');break;
}
if(k==true) return true;
else return false;
}
}
}
else if(d=='E')
{
int dx,dy;
for(int i=0;i<4;i++)
{
dx=x+ne[i][0];
dy=y+ne[i][1];
if(book[dx][dy]==4) return false;
if(dx==ex&&dy==ey) return true;
book[dx][dy]++;
if(dx<1||dy<1||dx>n||dy>m||map[dx][dy]=='#') continue;
else
{
bool k;
switch(i)
{
case 0:k=dfs(dx,dy,'N');break;
case 1:k=dfs(dx,dy,'E');break;
case 2:k=dfs(dx,dy,'S');break;
case 3:k=dfs(dx,dy,'W');break;
}
if(k==true) return true;
else return false;
}
}
}
else if(d=='W')
{
int dx;
int dy;
for(int i=0;i<4;i++)
{
dx=x+nw[i][0];
dy=y+nw[i][1];
if(book[dx][dy]==4) return false;
if(dx==ex&&dy==ey) return true;
book[dx][dy]++;
if(dx<1||dy<1||dx>n||dy>m||map[dx][dy]=='#') continue;
else
{
bool k;
switch(i)
{
case 0:k=dfs(dx,dy,'S');break;
case 1:k=dfs(dx,dy,'W');break;
case 2:k=dfs(dx,dy,'N');break;
case 3:k=dfs(dx,dy,'E');break;
}
if(k==true) return true;
else return false;
}
}
}
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(book,0,sizeof(book));
getchar();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
scanf("%c",&map[i][j]);
if(map[i][j]=='T')
{
bx=i;
by=j;
}
if(map[i][j]=='X')
{
ex=i;
ey=j;
}
}
getchar();
}
scanf("%c",&dir);
getchar();
if(dfs(bx,by,dir)) printf("YES\n");
else printf("NO\n");
}
return 0;
}