求解迷宫问题(用栈和队列分别求解)

代码如下

  • 这是栈的解法:
#include
#include
#include
#define M 8
#define N 8
#define MaxSize 100
//每个元素表示一个方块,为0对应的通道,为1对应的为墙
int mg[M + 2][N + 2] =
{ {1,1,1,1,1,1,1,1,1,1,},
  {1,0,0,1,0,0,0,1,0,1},
  {1,0,0,1,0,0,0,1,0,1},
  {1,0,0,0,0,1,1,0,0,1},
  {1,0,1,1,1,0,0,0,0,1},
  {1,0,0,0,1,0,0,0,0,1},
  {1,0,1,0,0,0,1,0,0,1},
  {1,0,1,1,1,0,1,1,0,1},
  {1,1,0,0,0,0,0,0,0,1},
  {1,1,1,1,1,1,1,1,1,1} }; 

	typedef struct {
	int i;  //当前方块的行号
	int j;  //当前方块的列号
	int di;   //di是下一个可行走的相邻方块的方位号
}Box;
typedef struct {
	Box data[MaxSize];
	int top;
}StType;

int mgpath(int xi, int yi, int xe, int ye) {//求解的路径为(xi,yi)-->(xe,ye)
	int i, j, k, di, find;
	StType st;
	st.top = -1;
	st.top++;
	st.data[st.top].i = xi;
	st.data[st.top].j = yi;
	st.data[st.top].di = -1;
	mg[xi][yi] = -1;
	while (st.top > -1) {
		i = st.data[st.top].i;
		j = st.data[st.top].j;
		di = st.data[st.top].di;
		if (i == xe && j == ye) {
			printf("迷宫路径如下\n");
			for (k = 0; k <= st.top; k++) {
				printf("(%d,%d)", st.data[k].i, st.data[k].j);
				if (k % 5 == 0) printf("\n");
			}
			return 1;//找到路径,返回真
		}
		find = 0;
		while (di < 4 && find == 0) {//寻找下一个方块
			di++;
			switch (di) {
			case 0:i = st.data[st.top].i + 1, j = st.data[st.top].j;
				break;
			case 1:i = st.data[st.top].i, j = st.data[st.top].j + 1;
				break;
			case 2:i = st.data[st.top].i - 1, j = st.data[st.top].j;
				break;
			case 3:i = st.data[st.top].i, j = st.data[st.top].j - 1;
				break;
			}
			if (mg[i][j] == 0) find = 1;
		}
		if (find == 1) {
			st.data[st.top].di = di;
			st.top++;
			st.data[st.top].i = i;
			st.data[st.top].j = j;
			mg[i][j] = -1;  //避免重复走到该方块
		}
		else {    //没录可走,则退栈
			mg[st.data[st.top].i][st.data[st.top].j] = 0;
			st.top--;  //将该方块退栈
		}
	}
	return 0;//没有路径可走,返回假
}

int main() {
	if (!mgpath(1, 1, M, N)) {
		printf("该问题无解!");
	}
}

此解不一定是最优解,即不是最短路径!

下面的为最优解

  • 用队列的思想
#include
#include
#include
#define M 8
#define N 8
#define MaxSize 100
//每个元素表示一个方块,为0对应的通道,为1对应的为墙
int mg[M + 2][N + 2] =
{ {1,1,1,1,1,1,1,1,1,1,},
  {1,0,0,1,0,0,0,1,0,1},
  {1,0,0,1,0,0,0,1,0,1},
  {1,0,0,0,0,1,1,0,0,1},
  {1,0,1,1,1,0,0,0,0,1},
  {1,0,0,0,1,0,0,0,0,1},
  {1,0,1,0,0,0,1,0,0,1},
  {1,0,1,1,1,0,1,1,0,1},
  {1,1,0,0,0,0,0,0,0,1},
  {1,1,1,1,1,1,1,1,1,1} };

typedef struct {
	int i, j;//方块位置
	int pre;//本路径中上一块在队列中的下标
}Box;
typedef struct {
	Box data[MaxSize];
	int front, rear;
}QuType;

void print(QuType qu, int front) {
	int k = front, j;
	do {//反向找到最短的路径,将该路径上的方块的pre标记为-1
		j = k;
		k = qu.data[k].pre;
		qu.data[j].pre = -1;
	} while (k != -1);
	for (k = 0; k < MaxSize; k++) {//正向搜索pre为-1的方块,即构成正向路径
		if (qu.data[k].pre == -1)
			printf("(%d,%d)   ", qu.data[k].i, qu.data[k].j);
	}
	printf('\n');
}
int mgpath(int xi, int yi, int xe, int ye) {
	int i, j, find = 0, di;
	QuType qu;
	qu.front = qu.rear = -1;
	qu.rear++;
	qu.data[qu.rear].i = xi;
	qu.data[qu.rear].j = yi;
	qu.data[qu.rear].pre = -1;
	mg[xi][yi] = -1;  //将其赋值为1,以避免回过来重复搜索
	while (qu.front != qu.rear && !find) {//队列不为空且找到路径时循环
		qu.front++;   //出队,由于不是韩星队列,该队列元素任然在队列中
		i = qu.data[qu.front].i;
		j = qu.data[qu.front].j;
		if (i == xe && j == ye) {//找到出口
			find = 1;
			print(qu, qu.front);
			return 1;
		}
		for (di = 0; di < 4; di++) {//扫描各个方位,并把可走的方位放到队列中
			switch (di) {
			case 0:i = qu.data[qu.front].i + 1, j = qu.data[qu.front].j; break;
			case 1:i = qu.data[qu.front].i, j = qu.data[qu.front].j + 1; break;
			case 2:i = qu.data[qu.front].i - 1, j = qu.data[qu.front].j; break;
			case 3:i = qu.data[qu.front].i, j = qu.data[qu.front].j - 1; break;
			}
			if (mg[i][j] == 0) {
				qu.rear++;
				qu.data[qu.rear].i = i;
				qu.data[qu.rear].j = j;
				qu.data[qu.rear].pre = qu.front;//保存路径上一个方块的下标
				mg[i][j] = -1;//将其赋值为1,以避免回过来重复搜索
			}
		}
	}
	return 0;
}


int main() {
	if (!mgpath(1, 1, M, N))
		printf("该问题无解!");
}

你可能感兴趣的:(求解迷宫问题(用栈和队列分别求解))