这道也是典型的DFS迷宫。算是简单的了。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/*对于此题的理解 一开始认为与走砖块差不多但后来发现有很多地方我实现不了 学习了此题便可以解决一系列找宝藏问题 这题重要的地方就是 1.奇偶剪枝 2.找到目标退出(最优路径便无需推出) 3.方向循环里该如何编写的学习 4.墙数与地图可行数对题目的优化*/ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; char map[10][10]; int visit[10][10]; int n,m,t,ex,ey,flag; void dfs(int sx,int sy,int step) { int i,dx,dy; int next[4][2]={{-1,0},{1,0},{0,1},{0,-1}};//方向数组 if(flag)//很重要,可以减少步骤,也是如何使一旦找到需要的路线就可以连续return出 return; if(sx==ex&&sy==ey&&step==t) { flag=1; return; } int tem=t-step-abs(ex-sx)-abs(ey-sy);//剪枝的核心代码 if(tem<0||tem&1)//剪枝:如果剩余的步数已经不足以走到出口,且必须是偶数,偶数-偶数=偶数,奇数-奇数=偶数, return; for(i=0;i<4;i++) { dx=sx+next[i][0]; dy=sy+next[i][1]; if(dx<0||dy>=m||dy<0||dx>=n) continue; if(map[dx][dy]!='X'&&visit[dx][dy]==0) { visit[dx][dy]=1;//及时标记,先判断后标记,先确定能不能走 ,在考虑走完标记的问题 dfs(dx,dy,step+1); if(flag)//若找到结果,及时return return; visit[dx][dy]=0;//注意返回标记 以便下次搜索 } } return ; } int main() { int i,j,wall; int sx,sy; while(~scanf("%d %d %d",&n,&m,&t)) { if(n==0&&m==0&&t==0) break; flag=0;wall=0; memset(visit,0,sizeof(visit)); for(i=0;i<n;i++) { scanf("%s",map[i]); } for(i=0;i<n;i++) { for(j=0;j<m;j++) { if(map[i][j]=='S') { sx=i;sy=j; } if(map[i][j]=='D') { ex=i;ey=j; } if(map[i][j]=='X') wall++; } } if(t>n*m-wall-1)//注意时间与墙数和地图的数量关系会减少很多步骤哦 { printf("NO\n"); continue; } visit[sx][sy]=1;//务必记得标记走过的路径 dfs(sx,sy,0); if(flag==1) printf("YES\n"); else printf("NO\n"); } return 0; }