数据结构书上已经讲了算法,可是还是写了好久。
大方向使用栈(stack)来写,因为要顺着某一方向向前探索,如果能通(ps:可通,表示其未曾走到过,当然也不能是墙块),继续向前走;否则沿着来路退回一格,换一个方向再探索,直到所有的通路都探索完为止;为了保证任何位置都能沿原路退回,就需要一个先进后出的结构来保存当前路径,所以可以用栈;
具体思路: 1.从入口块开始,判断其是否“可通”,如果是压入栈,并把下面的一块置为当前块(如果没有下边的块,就按下,上,左,右的顺序找出第一块,记住是第一块),同时,留下“足迹”,当然如果又是“出口块”,路径就完成了;
2.否则原路退回路径末端,即栈顶,如果栈顶块还有其他方向没有探索就按(下,上,左,右)一一探索,否则删除栈顶,继续测试栈顶,不合格就删除,直至找到一个还有方向可探索的栈顶或出栈至栈空;
3.结束条件就是栈空或路径到达出口。
代码细节:1.块用一个结构存储,例如:
struct node
{
int flag, i, j, track, di;//1--wall 0--room <i,j> track 表示是否曾走到过 di:有几个方向被探索过
};
typedef struct node Room;
2.迷宫可以用一个动态的一维数组存储。下标换算为index=i*n+j;求临块也很简单(别越界就行)。
Room *maze = NULL;
maze = (Room*)malloc(sizeof(Room) *n * m);
for(int i=0;i<m;i++)
for (int j = 0; j < n; j++)
{
scanf("%d", &maze[i * n + j].flag);
maze[i * n + j].i = i;
maze[i * n + j].j = j;
maze[i * n + j].track = 0;
maze[i * n + j].di = 0;
}
3.路径的栈
stack *solution=NULL;
solution = (stack*)malloc(n * m * sizeof(stack));
if (solution == NULL)exit(0);
solution->stackSize = n * m;
solution->top = solution->base = (Room*)malloc(n *m * sizeof(Room));
if (solution->top == NULL)exit(0);
//initial
//The space is enough ,so add the new top element straightly;
4.栈的操作
int stackEmpty(stack *solution)
{
int flag = 0;
if (solution->base == solution->top) flag = 1;
return flag;
}
Room *getTop(stack *solution)
{
Room *p = NULL;
if (!stackEmpty(solution)) p = solution->top - 1;
return p;
}
void pop(stack *solution)//delete the top of the stack;
{
if (!stackEmpty(solution)) solution->top--;
}
5.可通的判断
int pass(Room *currentRoom)
{
int isPass = 0;
if (currentRoom!=NULL&¤tRoom->track == 0&¤tRoom->flag==0)isPass = 1;// track==0 and flag==0;
return isPass;
}
等
完整代码
#include<stdio.h>
#include<stdlib.h>
struct node
{
int flag, i, j, track, di;//1--wall 0--room
};
typedef struct node Room;
struct Node
{
Room *top, *base, oneRoom;
int stackSize;
};
typedef struct Node stack;
int main()
{
Room *getTop(stack *solution);
int stackEmpty(stack *solution);
void pop(stack *solution);
int pass(Room * current);
Room *nextRoom(Room * p, int m, int n, Room *maze);
//creat the maze
int m, n, isPass = 0;
scanf("%d%d", &m, &n);
Room *maze = NULL;
maze = (Room*)malloc(sizeof(Room) *n * m);
for(int i=0;i<m;i++)
for (int j = 0; j < n; j++)
{
scanf("%d", &maze[i * n + j].flag);
maze[i * n + j].i = i;
maze[i * n + j].j = j;
maze[i * n + j].track = 0;
maze[i * n + j].di = 0;
}
//creat a stack;
//printf("test!!!\n");
/*for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
printf("%d <%d,%d>", maze[i*n + j].flag, maze[i*n + j].i, maze[i*n + j].j);
printf("\n");
}*/
stack *solution=NULL;
solution = (stack*)malloc(n * m * sizeof(stack));
if (solution == NULL)exit(0);
solution->stackSize = n * m;
solution->top = solution->base = (Room*)malloc(n *m * sizeof(Room));
if (solution->top == NULL)exit(0);
//initial
//The space is enough ,so add the new top element straightly;
Room *currentRoom = NULL, *p = NULL;
//printf("maze[0]:%d\n", maze[0]);
currentRoom = maze;// the entrence
//printf("test0.5!!!\n");
do
{
//printf("test1!!!\n");
//if (currentRoom != NULL)printf("test!!! currentRoom :<%d,%d>\n", currentRoom->i + 1, currentRoom->j + 1); else printf("test!!! currentRoom :NULL\n");
isPass = pass(currentRoom);
//printf("pass:%d\n", isPass);
if(currentRoom!=NULL)currentRoom->track = 1;//leave the track;
if (isPass)// pass,so store in stack
{
*solution->top++ = *currentRoom;
if (currentRoom->i==m-1&¤tRoom->j==n-1)break;// the destination
p = getTop(solution);
p->di += 1;
//printf("test!!!top :<%d,%d> id:%d\n", p->i + 1, p->j + 1, p->di);
currentRoom = nextRoom(p,m,n,maze);//next room;
}
else
{
if (!stackEmpty(solution))
{
p = getTop(solution);
if (p->di < 4)
{
//printf("test!!!top :<%d,%d> id:%d\n", p->i + 1, p->j + 1, p->di);
p->di += 1;
//printf("test!!!top :<%d,%d> id:%d\n", p->i + 1, p->j + 1, p->di);
currentRoom = nextRoom(p, m, n, maze);
}// other direction
else
{
//printf("di>=4\n");
pop(solution);
while (!stackEmpty(solution) && getTop(solution)->di == 4)
pop(solution);// back
if (!stackEmpty(solution))
{
p = getTop(solution);
//printf("test!!!top :<%d,%d> id:%d\n", p->i + 1, p->j + 1, p->di);
p->di += 1;
// printf("test!!!top :<%d,%d> id:%d\n", p->i + 1, p->j + 1, p->di);
//printf("test!!!top :<%d,%d> id:%d\n", p->i + 1, p->j + 1, p->di);
currentRoom = nextRoom(p, m, n, maze);
}
}
}
}
} while (!stackEmpty(solution));
//output.
if (stackEmpty(solution))printf("There is no solution!\n");
else
{
while (solution->base != solution->top)
{
printf("<%d,%d> ", solution->base->i + 1, solution->base->j + 1);
solution->base++;
}
printf("\n");
}
}
int pass(Room *currentRoom)
{
int isPass = 0;
if (currentRoom!=NULL&¤tRoom->track == 0&¤tRoom->flag==0)isPass = 1;// track==0 and flag==0;
return isPass;
}
int stackEmpty(stack *solution)
{
int flag = 0;
if (solution->base == solution->top) flag = 1;
return flag;
}
Room *getTop(stack *solution)
{
Room *p = NULL;
if (!stackEmpty(solution)) p = solution->top - 1;
return p;
}
void pop(stack *solution)//delete the top of the stack;
{
if (!stackEmpty(solution)) solution->top--;
}
Room *nextRoom(Room * p,int m,int n,Room *maze)
{
//printf("testNext\n");
Room *next = NULL;
//printf("test!!!top :<%d,%d> id:%d i:%d j:%d\n", p->i + 1, p->j + 1, p->di,p->i,p->j);
int i = p->i, j = p->j;
if (p->di > 4||p->di<1)p->di = 4;
//printf("testNext0.1\n");
if (p->di == 1)
{
if (i + 1 > m - 1)p->di += 1;
else next = &maze[(i + 1)*n + j];
}
if (p->di == 2)
{
if (j + 1 > n - 1)p->di += 1;
else next = &maze[i*n + j + 1];
}
if (p->di == 3)
{
if (i - 1 < 0)p->di += 1;
else next = &maze[(i - 1)*n + j];
}
if (p->di == 4)
if (j - 1 >= 0) next = &maze[i*n + j - 1];
//printf("testNext1\n");
return next;
}
虽然不复杂但我还是问题百出,最无语的是把入口块赋值给currentRoom时,开始用了*currentRoom=maze[0];然后就直接崩了,调了半天才发现*(取内容)是取不到能容的,因为指针初值为NULL;