题目大意:给出一个N*M的迷宫,迷宫中有一扇门D,只有在T时刻会打开,现在你0时刻位于S,你需要在正好在T时刻到达D,你只能上下左右移动,每次移动耗费1时刻,且同一个位置不能进入两次,问是否能在T时刻刚好到达D处。
范围 1 < N,M < 7, 1 < T < 50,这个范围有点大,直接DFS回溯搜会TLE,我们要加上一个剪枝,这个剪枝十分重要,我们求出起点到终点的距离(横向距离 + 纵向距离),若这个距离为奇数,则时间T必须也要为奇数,否则时间T必须为偶数(其中的道理显而易见),只有这样,你才有可能在T时刻到达D。详情见下面的代码:
1 #include2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 using namespace std; 9 10 typedef long long LL;11 typedef unsigned long long ULL;12 const int dx[] = { 1,-1,0,0};13 const int dy[] = { 0,0,1,-1};14 15 int N, M, T, bx, by, ex, ey;16 char Map[10][10];17 int vis[10][10];18 19 bool dfs(int x, int y, int t){20 if(x == ex && y == ey && t == T) return true;21 if(t >= T) return false;22 for(int i = 0; i < 4; ++i){23 int nx = x + dx[i];24 int ny = y + dy[i];25 if(nx >= 0 && ny >= 0 && nx < N && ny < M){26 if(vis[nx][ny]) continue;27 if(Map[nx][ny] == 'X') continue;28 vis[nx][ny] = 1;29 if(dfs(nx, ny, t+1)) return true;30 vis[nx][ny] = 0;31 }32 }33 return false;34 }35 36 int main(){37 while(scanf("%d%d%d", &N, &M, &T) == 3 && N){38 for(int i = 0; i < N; ++i){39 scanf("%s", Map[i]);40 for(int j = 0; j < M; ++j)41 if(Map[i][j] == 'D') {42 ex = i;43 ey = j;44 }else if(Map[i][j] == 'S') {45 bx = i;46 by = j;47 }48 }49 50 //奇偶剪枝51 int dis = abs(bx-ex)+abs(by-ey);52 if(dis%2 != T%2) {53 printf("NO\n");54 continue;55 }56 57 memset(vis, 0, sizeof(vis));58 vis[bx][by] = 1;59 if(dfs(bx, by, 0)) printf("YES\n");60 else printf("NO\n");61 }62 return 0;63 }