题意:在一个n*m迷宫上,规定一个起点和终点,有墙‘X’ ,问起点到终点能不能恰好K步,走过的路不能再走。
思路:暴力深搜,直接TLE。
自己想了好几种剪枝,最重要的剪枝:map奇偶剪枝之前没有接触过...就一直TLE。
介绍一下奇偶剪枝,在对一个地图进行01编号
0 1 0 1 0 1
很明显,如果起点在0 而终点在1 那显然 要经过奇数步才能从起点走到终点,依次类推,奇偶相同的偶数步,奇偶不同的奇数步在读入数据的时候就可以判断,并且做剪枝,当然做的时候并不要求把整个矩阵0,1刷一遍,读入的时候起点记为(Si,Sj) 终点记为(Di,Dj) 判断(Si+Sj) 和 (Di+Dj) 的奇偶性就可以了。
还有几个常见的剪枝
1.地图上能走的点数小于要求的步数,直接NO
2,最初出发点到目的点的最短路径小于要求步数,直接NO,还可以推出在搜索过程中当前点到目的点的最短路程小于还剩小路程.
3.在搜索过程步数已经大于等于要求步数,还没找到,或者是到了目的地,步数不对。
剪完后 78ms可以过
#include<bits/stdc++.h> using namespace std; char M[10][10]; int sx,sy,mx,my,n,m,w,flag,nxt[4][2]={0,1,1,0,0,-1,-1,0}; void dfs(int x,int y,int cur) { if(x==mx&&y==my){ if(cur==w) flag=1; return; } if(abs(x-mx)+abs(y-my)>w-cur) return;//可惜没神马卵用。 if(cur>=w) return; for(int i=0;i<4;i++){ int tx=x+nxt[i][0]; int ty=y+nxt[i][1]; if(tx<0||ty<0||tx>=n||ty>=m||M[tx][ty]=='X') continue; M[tx][ty]='X'; dfs(tx,ty,cur+1); if(flag) return; M[tx][ty]='.'; } } int main() { while(scanf("%d %d %d",&n,&m,&w)){ if((n+m+w)==0) return 0; int wall=0;flag=0; for(int i=0;i<n;i++){ scanf("%s",M[i]); for(int j=0;j<m;j++){ if(M[i][j]=='S') sx=i,sy=j; else if(M[i][j]=='D') mx=i,my=j; else if(M[i][j]=='X') wall++; } } if((mx+my+sy+sx+w)%2||n*m-wall<=w||abs(sx-mx)+abs(sy-my)>w){ printf("NO\n"); continue; } M[sx][sy]='X'; dfs(sx,sy,0); if(flag) printf("YES\n"); else printf("NO\n"); } }