求迷宫中从入口到出口的所有路径是一个经典的问题,这里所使用的方法是递归法,什么是递归呢?函数中有调用自己的函数,我们称为递归函数。一个问题可以分解为一个与自身求解过程相同的小问题,我们都可以用递归,比如,Hanoi塔问题,八皇后问题。我们知道用递归方法求解问题时最关键的就是递归函数的设计,在设计递归函数时应该注意以下几点:
1.严格定义函数的功能和接口,对函数中所得的和原问题性质相同的子问题,只要接口一致,便可进行递归调用;
2.对函数中每个递归调用都看成是一个简单的语句,切忌想得太深。
其实,在使用递归的时候我们可以想一下归纳法的思想,如果n成立,我们即可使用n的结论来计算n+1,在计算n+1时无需想着n+1之前的n是如何计算的,因为我们已经假设n已经成立了,无需在怀疑它的正确性。
下面给出使用递归法求解迷宫问题的源代码,代码中求出了共有多少条道路可以通。
/*
* 求迷宫中有多少条可通路径,1表示城墙,0表示道路
*/
#include <stdio.h>
#include <stdlib.h>
struct point{
int p[10][10];
int mark[10][10];
};
struct point pt;
int c = 0;
void build_maze(void)
{
FILE *fd;
char c;
int i = 0,j;
fd = fopen(“maze.txt”,”r”); //maze.txt中画有迷宫地图
while(!feof(fd)){
c = fgetc(fd);
if(isdigit(c)){
pt.p[i/10][i%10] = c – 48;
pt.mark[i/10][i%10] = 0;
i++;
}
}
fclose(fd);
return;
}
int maze(int x,int y)
{
/*
*当进入函数时,已经处在迷宫的(x,y)座标位置;
*现在从(x,y)相邻的四个方向前进,前进条件是,该方向能通(值为0),并且还没有走过(0表示没走过);
*当(x,y) == (8,8)终点时,表示求得一条可通路径
*/
int i,j;
if (x == 8 && y == 8) { //OUT
c++;
return 1;
}
if (x – 1 >= 0 ) { //东方
if (pt.p[x – 1][y] == 0) {
if (pt.mark[x – 1][y] == 0) {
pt.mark[x – 1][y] = 1;
maze(x – 1,y);
pt.mark[x – 1][y] = 0; //退回,将走过的标记清除
}
}
}
if (y + 1 <= 9){
if (pt.p[x][y + 1] == 0 ){
if (pt.mark[x][y + 1] == 0) {
pt.mark[x][y + 1] = 1;
maze(x,y + 1);
pt.mark[x][y + 1] = 0;
}
}
}
if (x + 1 <= 9){
if (pt.p[x+1][y] == 0){
if (pt.mark[x + 1][y] == 0) {
pt.mark[x + 1][y] = 1;
maze(x + 1,y);
pt.mark[x + 1][y] = 0;
}
}
}
if (y – 1 >= 0){
if (pt.p[x][y – 1] == 0){
if(pt.mark[x][y – 1] == 0) {
pt.mark[x][y – 1] = 1;
maze(x,y – 1);
pt.mark[x][y – 1] = 0;
}
}
}
return 0;
}
/* Find a way to go out of the maze */
int main()
{
int i,j;
build_maze();
pt.mark[1][1] = 1;
maze(1,1);
if(c > 0) {
printf(“There are %d ways for us to go out!/n”,c);
}
else
printf(“Can’t go out!/n”);
/* 打印迷宫地图 */
for(i = 0;i<10;i++){
for(j = 0;j < 10;j++){
printf(“%d”,pt.p[i][j]);
}
printf(“/n”);
}
return 0;
}