大二时学数据结构有学过深度优先搜索(DFS)和广度有限搜索(BFS) 。而由于大二偷懒了。虽然知道大概的意思,但是完全用不了。导致了这题搁浅了很久,拜访各大神博客终于是大概知道了做法。代码也很多是参考别人的了,所以说虽然这篇写着原创。但很多都是其他地方转来的。添加一些自己个人的理解以及注释。希望和我一样困入DFS的朋友看了能有所帮助。
好了,进入正题。显然,这题是用DFS来做的。具体什么是DFS,DFS怎么用请参考数据结构相关材料。
但是毕竟是OJ 有一个很大的要考虑的问题,就是RUNTIMEERROR,所以,我们应该尽可能的剪枝避免超时。那么这道题目有如下几种可以剪枝的地方:
1、如果已花时间大于规定时间则此条路径无效,返回;
2、如果找到符合的情况则不再找其他路径;
3、如果(剩下能走的距离-当前点与出口的步数)%2不为0,则同样此条路径无效
其中第3条是为了考虑老鼠不是找最短的路到达的情况,比如下面的
S 。。。
。。X 。
。。D 。
。。。。到达D的可能时间有4,6,8,10,12,14,看规律都是成偶数个数递增的。
代码如下:
#include <iostream> using namespace std; #define N 10 bool result; char a[N][N]; //定义存储数组 int n,m,t; //定义矩阵大小及时间 int dx,dy;//门的位置 void search(int x,int y,int cnt) //形参:起始坐标、所用时间 { if(result) //不断往回推 return; if(a[x][y]=='D'&&cnt==t) //递归子查询使用 { result=true; return; } if(cnt>t||((t-cnt)-abs(x-dx)-abs(y-dy))%2!=0) //剪枝关键环节,每次都要测,可以减少很多的时间 return; char temp=a[x][y]; //现场保护用, a[x][y]='X'; if(!result&&x>1&&a[x-1][y]=='.'||a[x-1][y]=='D') //这里形参不可用自加、自减运算否则会出错 search(x-1,y,cnt+1); if(!result&&x<n&&a[x+1][y]=='.'||a[x+1][y]=='D') search(x+1,y,cnt+1); if(!result&&y>1&&a[x][y-1]=='.'||a[x][y-1]=='D') search(x,y-1,cnt+1); if(!result&&y<m&&a[x][y+1]=='.'||a[x][y+1]=='D') search(x,y+1,cnt+1); a[x][y]=temp; } int main() { while(1) { int sx,sy; //起点坐标 cin>>n>>m>>t; if(!n&&!m&&!t) break; result=false; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { cin>>a[i][j]; if(a[i][j]=='S'){ sx=i; sy=j;} if(a[i][j]=='D'){ dx=i; dy=j;} } if((abs(sx-dx)+abs(sy-dy)-t)%2==0) search(sx,sy,0); if(result) printf("YES\n"); else printf("NO\n"); } return 0; }
总结:这道题目应用了较为简单的DFS,确实也是一道不错的题目,做很多其他迷宫类题目的原型。