/*逃离迷宫
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,即从起点出发无论从哪个方向出发,这个出发方向都不会被算进拐弯次数内。