/*逃离迷宫 Time Limit : 1000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other) Total Submission(s) : 0 Accepted Submission(s) : 0 Font: Times New Roman | Verdana | Georgia Font Size: ← → Problem Description 给定一个m × n (m行, n列)的迷宫,迷宫中有两个位置,gloria想从迷宫的一个位置走到另外一个位置,当然迷宫中有些地方是空地,gloria可以穿越, 有些地方是障碍,她必须绕行,从迷宫的一个位置,只能走到与它相邻的4个位置中,当然在行走过程中,gloria不能走到迷宫外面去。令人头痛的是, gloria是个没什么方向感的人,因此,她在行走过程中,不能转太多弯了,否则她会晕倒的。我们假定给定的两个位置都是空地,初始时, gloria所面向的方向未定,她可以选择4个方向的任何一个出发,而不算成一次转弯。gloria能从一个位置走到另外一个位置吗? Input 第1行为一个整数t (1 ≤ t ≤ 100),表示测试数据的个数,接下来为t组测试数据,每组测试数据中, 第1行为两个整数m, n (1 ≤ m, n ≤ 100),分别表示迷宫的行数和列数,接下来m行,每行包括n个字符,其中字符'.'表示该位置为空地, 字符'*'表示该位置为障碍,输入数据中只有这两种字符,每组测试数据的最后一行为5个整数k, x1, y1, x2, y2 (1 ≤ k ≤ 10, 1 ≤ x1, x2 ≤ n, 1 ≤ y1, y2 ≤ m),其中k表示gloria最多能转的弯数,(x1, y1), (x2, y2)表示两个位置,其中x1,x2对应列, y1, y2对应行。 Output 每组测试数据对应为一行,若gloria能从一个位置走到另外一个位置,输出“yes”,否则输出“no”。 Sample Input 2 5 5 ...** *.**. ..... ..... *.... 1 1 1 1 3 5 5 ...** *.**. ..... ..... *.... 2 1 1 1 3 Sample Output no yes Source “网新恩普杯”杭州电子科技大学程序设计邀请赛 */ #include<stdio.h> char map[110][110]; int m, n, dx[4] = {0,0,1,-1}, dy[4] = {1,-1,0,0}, x1, y1, x2, y2, f[110][110], dir[110][110], k; void dfs(int x, int y) { int nx , ny, i, j; if(x == y2 && y == x2)//end return ; for(i = 0; i < 4; ++i) { nx = x + dx[i]; ny = y + dy[i]; if(nx >= 0 && nx < m && ny >= 0 && ny < n && map[nx][ny] != '*' ) { if(dir[x][y] != i + 1) { if(f[x][y] + 1 <= f[nx][ny] && f[x][y] + 1 <= k)//use the f[] to save the minimum corners { //use the dir[] to save the direction f[nx][ny] = f[x][y] + 1; dir[nx][ny] = i+1; dfs(nx,ny); } } else { if(f[x][y] <= f[nx][ny] && f[x][y] <= k) { f[nx][ny] = f[x][y]; dir[nx][ny] = i+1; dfs(nx,ny); } } } } } int main() { int t , i, j; scanf("%d", &t); while(t--) { scanf("%d%d", &m, &n); for(i = 0; i < m; ++i) scanf("%s", map[i]); scanf("%d%d%d%d%d", &k, &x1, &y1, &x2, &y2); //initial x1 -= 1; y1 -= 1; x2 -= 1; y2 -= 1; for(i = 0; i < m; ++i) for(j = 0; j < n; ++j) f[i][j] = 10010; f[y1][x1] = -1; dir[y1][x1] = 0; map[y1][x1] = '*'; dfs(y1, x1); if((x1 == x2 && y1 == y2) || f[y2][x2] <= k ) printf("yes\n"); else printf("no\n"); } return 0; }
题意:给出一个迷宫,并且给出起点和终点,求起点到终点所需要的最小的转弯次数,并与题目给出的转弯次数相比较,小于等于的情况下输出yes,说明能够在有限的转弯次数内走到终点,否则输出no。
思路:常规的深搜会超时,需要用两个数组的空间来换取时间,即一个数组用来存储起点到当前点的的最小拐弯次数,另一个数组记录在该最小拐弯次数情况下该点来时的方向。所以在每移动一个位置时,即可以判断移动后该点是否拥有新的最小的拐弯次数,如果有,则以该点接着往其他方向搜索,如果没有,则这个方向不再遍历。以此类推,直至走完整个地图,则数组中保存的终点中的值即为最小的拐弯次数。
注意:起点的初始方向不能和四个方向相同,并且要将起点的拐弯次数设置为-1,即从起点出发无论从哪个方向出发,这个出发方向都不会被算进拐弯次数内。