Description
有一个N*M(N,M<=10)的格子迷宫,1代表该格子为墙,不能通过,0代表可以通过,人在迷宫中可以尝试上下左右四个方向移动。 另外,在迷宫中如果从左边走出迷宫会回到迷宫最右边一格(只要该格不是墙),行不变,同样,从右边走出迷宫会 回到迷宫最左边一格,向上走出迷宫会回到迷宫最下边一格,向下走出迷宫会回到迷宫最上边一格。 现在给定一个迷宫,以及起点和终点,问最少多少步可以走出迷宫。如果不能走出迷宫输出“die”。
输入格式
该程序为多CASE,第1行为CASE的数量 每一个CASE,第1行为两个数N(行)和M(列) 然后N行每行M个数,之后是起点坐标和终
输入样例
2 4 3 011 010 110 110 0 0 3 2 2 2 01 10 0 0 1 1
输出样例
4 die
我看到网上都是使用栈DFS和队列BFS来做这道题,但是做法其实是不符合题意的。本题要求最短的路径,所以涉及到比较关系。
迷宫问题使用记忆化搜索算法和动态规划算法求解是很好的选择。这里使用记忆化搜索。
递归的终止条件:
1、当前坐标mapp[y][x] == '1'时,返回一个大数,这里随便写了个10000
2、当前坐标为起始点,x==sc && y==sr,返回0
递归体:
1、遍历过的点map[y][x]赋值为‘1’
2、记忆化搜索查询dp[y][x]是否有答案,有则返回,没有则递归
3、来到当前点的最短路径dp[y][x]等于四个方向的最短路径 + 1
4、返回dp[y][x]
int n,m;
char map[11][11];
int dp[11][11];
int pocess(int x, int y, int sc, int sr)
{
if(x == -1)
x = m-1;
else if(x == m)
x = 0;
if(y == -1)
y = n-1;
else if(y == n)
y = 0;
if(map[y][x] == '1')
return 10000;
if(x==sc && y==sr)
return 0;
map[y][x] = '1';
if(dp[y][x] != -1)
return dp[y][x];
dp[y][x] = min(min(pocess(x+1, y, sc , sr), pocess(x-1, y, sc , sr)),
min(pocess(x, y+1, sc , sr), pocess(x, y-1, sc , sr)))
+1;
return dp[y][x];
}
int main()
{
int t;
cin >> t;
while(t--)
{
cin >> n >> m;
memset(map,1,sizeof(map));
memset(dp,-1,sizeof(dp));
int sc,sr,ec,er;
for(int i=0; i<n; i++)
{
string t;
cin >> t;
strcpy(map[i], t.c_str());
}
cin >> sr >> sc >> er >> ec;
pocess(ec,er,sc,sr);
if(dp[er][ec] != 10001)
cout << dp[er][ec] << endl;
else
cout << "die" << endl;
}
return 0;
}