Mitch老鼠在森林里嬉戏,不小心走进了一个迷宫内里,这个迷宫是一个 n 行 m 列的矩阵,迷宫中有些格子是可以走的,有些格子是不能走的,能走的格子用 o (小写字母 o )表现,不能走的格子用 # 表现。
Mitch选择走出迷宫的计谋是:先向右,如果右边走不通则选择向下,如果下边走不通则选择向左,如果左边走不通则选择向上;如果四个方向都走不通,则后退选择其他能走的路径。
Mitch从类似下图所示的迷宫的左上角点进入迷宫(请注意:入口 和出口的 点都不是 # ),叨教Mitch有哪些方法可以走出迷宫,走到(n,m) 点;请编程求出所有大概的路径,输出这些路径,如果不存在任何的路径可以走出迷宫,请输出 no。
输入
第一行包含两个整数 n 和 m ,中间用单个空格隔开,代表迷宫的行和列的数目。
接下来 n 行,每行 m 个字符,描述迷宫舆图。字符只有o 或 # 两种,o 代表这个格子可以走,# 代表这个格子不能走。(4≤n,m≤10 )
输出
请按照Mitch选择的走出迷宫的计谋,输出所有大概的路径,输出形式请参考样例输出的形式。
如果不存在任何的路径可以走出迷宫,请输出 no。
样例
输入
一只叫 Mitch 的老鼠在森林里嬉戏时误入了一个迷宫,这个迷宫出现为一个 n 行 m 列的矩阵形式。迷宫中的格子分为两种环境,能用小写字母 o 表现的格子是可以行走通过的,而用 # 表现的格子是不能走的 “停滞” 格子。Mitch 选择的走出迷宫计谋是有特定序次的,它会先实验向右走,如果右边走不通就向下走,向下走不通就向左走,向左走不通就向上走,要是四个方向都走不通,那就后退去选择其他能走的路径。Mitch 从迷宫的左上角(入口,且入口点不是 # )进入迷宫,需要编程求出它按照这个计谋能走出迷宫到达右下角点 (n, m) 的所有大概路径,并按照规定格式输出这些路径,如果不存在任何可行的走出迷宫的路径,那就输出 no 。
代码思路
这个函数的作用是按照规定格式输出一条找到的可行路径。它先输出路径的序号(也就是变量 t 的值),然后通过循环遍历已经记录在数组 a 中的坐标点,按照 x,y-> 的格式依次输出路径上经过的每个点,末了输出终点坐标 (n, mn) 。
void p(int c){
// 输出路径序号
printf("%d:",t);
for(int i=1;i<=c;i++){
// 输出路径上每个点的坐标格式
printf("%d,%d->",a[i][0],a[i][1]);
}
// 输出终点坐标
printf("%d,%d\n",n,mn);
}
复制代码
深度优先搜刮函数 dfs:
递归终止条件判断:首先判断当前位置 (x, y) 是否已经到达迷宫的右下角终点(即 x == n 且 y == mn),如果到达了终点,说明找到了一条可行路径,此时将路径数目 t 加 1,然后调用 p 函数输出这条路径(注意传入的参数是 c - 1,因为数组 a 中记录路径的下标是从 1 开始的,这里要输出的是前面已经记录好的有用坐标个数),末了返回竣事这次递归分支。
if(x==n&&y==mn){
t++;//到达终点,增加一个路径
p(c-1);
return;
}
复制代码
标志当前位置并记录坐标:将当前到达的位置 (x, y) 在迷宫数组 m 中标志为 #,表现已经走过了(制止重复走,起到类似剪枝的作用),然后把当前位置的坐标志录到数组 a 中,方便后续输出路径。
m[x][y]='#';//到达某点,标记
a[c][0]=x;
a[c][1]=y;
复制代码
实验四个方向探索:通过一个循环遍历四个方向(i 从 0 到 3,分别对应右、下、左、上四个方向),先计算出按照当前方向走一步后的坐标 h(横坐标)和 l(纵坐标),接着判断这个新坐标是否在迷宫范围内(h > 0 && h <= n && l > 0 && l <= mn)而且对应格子是可以走的(m[h][l] == 'o'),如果满足这些条件,就以这个新坐标为起点举行递归调用 dfs 函数,继承探索下一步的路径,同时传入的路径记录长度参数 c 要加 1,表现往下多走了一步,记录路径的位置今后移一位。
首先从标准输入读取迷宫的行数 n 和列数 mn,然后通过两层循环逐行逐列地读取迷宫的布局环境(字符 o 大概 #)并存入数组 m 中。接着以迷宫的左上角坐标 (1, 1) 作为起点,调用 dfs 函数开始深度优先搜刮路径,初始的路径记录长度参数设为 1。末了判断如果找到的路径数目 t 还是 0,说明没有找到任何可行路径,那就输出 no 。