迷宫问题

     数据结构书上已经讲了算法,可是还是写了好久。敲打

大方向使用栈(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;

截图

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值