笔试题:03年_迷宫

#include <stdio.h>
#include <stdlib.h>
#include <queue>

using namespace std;
//请编写一个迷宫程序

//广度优先寻找最短时间走出迷宫。深度优先遍历解决:能否走出迷宫。

#define MAXSIZE 128
bool bMark[MAXSIZE][MAXSIZE];    //剪枝标记数组,true:表示已经访问过,false:表示没有访问过
int iArrMaze[MAXSIZE][MAXSIZE]; //迷宫数组,0:表示墙,1:表示路
typedef struct Stat             //走路状态
{
	Stat(int iX,int iY,int iStep):_iX(iX),_iY(iY),_iStep(iStep){}
	int _iX;                  //横坐标
	int _iY;                  //纵坐标
	int _iStep;               //步数
}Stat;
queue<Stat> queueStat;      //广度优先必须设置队列,用队列是否为空作为循环跳出条件
int iArrGo[][2] = { {0,1} , {0,-1} ,{1,0} ,{-1,0}};//设置下一步走的标记
int iBegX,iBegY;//起始节点的坐标
int iEndX,iEndY;//终止节点的坐标
int iM,iN;      //迷宫的行长和列长
bool isSuccess = false;//设置找到出路的标记默认为假

int BFS(int iRow,int iCol)
{
	while(!queueStat.empty())
	{
		Stat curStat = queueStat.front();
		queueStat.pop();
		for(int i = 0 ; i < 4 ; i++)//4个方向,每个方向都需要遍历
		{
			int iNx = curStat._iX + iArrGo[i][0];
			int iNy = curStat._iY + iArrGo[i][1];
			
			//如果位置已经超出迷宫,则直接对下一个状态进行处理
			if(iNx < 0 || iNx >= iRow || iNy < 0 || iNy >= iCol )
			{
				continue;
			}

			//如果当前位置已经访问过,则不再访问
			if(true == bMark[iNx][iNy])
			{
				continue;
			}

			//如果当前位置是墙,则跳过
			if(1 == iArrMaze[iNx][iNy])
			{
				continue;
			}

			Stat nextStat(iNx,iNy,curStat._iStep + 1);
			queueStat.push(nextStat);//塞入下一个状态
			bMark[iNx][iNy] = true;   //置访问标记为真

			//判断是否抵达终点
			if(iNx == iEndX && iNy == iEndY)
			{
				return nextStat._iStep;//返回所走的步数
			}
		}
	}
	return -1;
}


void init()
{
	printf("请输入迷宫的大小(m*n):");
	scanf("%d %d",&iM,&iN);
	printf("请输入迷宫布局(1表示墙,0表示路):\n");
	for(int i = 0 ; i < iM ; i++)
	{
		for(int j =0 ; j < iN; j++)
		{
			//iArrMaze[i][j] = 
			scanf("%d",*(iArrMaze + i ) + j);
			bMark[i][j] = false;
		}
	}
	printf("\n请输入起始位置:");
	scanf("%d %d",&iBegX,&iBegY);
	printf("\n请输入结束位置:");
	scanf("%d %d",&iEndX,&iEndY);	
}

//采用深度优先,其实是用递归,这里不需要用到结构体。只能用来判定是否找到出口
void DFS(int iBegX,int iBegY)//由于要用到递归,这里必须给出初始的节点位置
{
	for(int i = 0 ; i < 4 ; i++ )
	{
		int iNx = iBegX + iArrGo[i][0];
		int iNy = iBegY + iArrGo[i][1];

		//如果位置超出迷宫范围
		if(iNx < 0 || iNx >= iM ||  iNy < 0 || iNy >= iN)
		{
			continue;
		}
		//如果当前位置是墙则跳过
		if(1 == iArrMaze[iNx][iNy])
		{
			continue;
		}
		//如果抵达终点
		if(iNx == iEndX && iNy == iEndY)
		{
			//printf("\n能够走出迷宫\n");
			isSuccess = true;
			return;
		}
		//递归之前,先设置当前位置为墙(1)
		iArrMaze[iNx][iNy] = 1;
		//接下来是递归调用
		DFS(iNx,iNy);
		//递归之后,由于还要回溯,因此需将当前位置设为路(0)
		iArrMaze[iNx][iNy] = 0;

		if(isSuccess == true)
		{
			return;
		}
	}
	//printf("\n不能走出迷宫\n");
}

void process()
{
	Stat statBeg(iBegX,iBegY,0);
	queueStat.push(statBeg);
	int iRes = BFS(iM,iN);
	if(iRes != -1)
	{
		printf("\n从起点(%d,%d)经过%d步可以到达终点(%d,%d)\n",iBegX,iBegY,iRes,iEndX,iEndY);
	}
	else
	{
		printf("\n从起点(%d,%d)不能到达终点(%d,%d)\n",iBegX,iBegY,iEndX,iEndY);
	}
}

/*
样例输入:
行长:9 ,列长:9
起始节点:1,1
终止节点:7,7
1	1	1	1	1	1	1	1	1
1	0	0	0	0	0	0	0	1
1	0	1	1	0	1	1	0	1
1	0	1	0	0	1	0	0	1
1	0	1	0	1	0	1	0	1
1	0	0	0	0	0	1	0	1
1	1	0	1	1	1	1	1	1
1	0	0	0	0	0	0	0	1
1	1	1	1	1	1	1	1	1
*/

int iMaze[9][9] = { 
{1,1,1,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,1},
{1,0,1,1,0,1,1,0,1},
{1,0,1,0,0,1,0,0,1},
{1,0,1,0,1,0,1,0,1},
{1,0,0,0,0,0,1,0,1},
{1,1,0,1,1,1,1,1,1},
{1,0,0,0,0,0,0,0,1},
{1,1,1,1,1,1,1,1,1}
};

int startI = 1,startJ = 1;//入口
int endI = 7 ,endJ = 7;//出口
void printMaze()
{
	for(int i = 0 ; i < 9 ; i++ )
	{
		for(int j = 0 ; j < 9 ; j++)
		{
			if(iMaze[i][j]==1)
			{
				printf("#");
			}
			else
			{
				printf(" ");
			}
		}
		printf("\n");
	}
}

void visit(int i,int j)
{
	iMaze[i][j] = 2;
	if(i==endI && j==endJ)
	{
		printf("\n显示路径:\n");
		for(int m = 0 ; m < 9 ; m++)
		{
			for(int n = 0 ; n < 9 ; n++)
			{
				if(iMaze[m][n]==1)
				{
					printf("#");
				}
				else if(iMaze[m][n]==2)
				{
					printf("%");
				}
				else
				{
					printf(" ");
				}
			}
			printf("\n");
		}
	}

	if(iMaze[i][j+1]==0)
	{
		visit(i,j+1);
	}
	if(iMaze[i+1][j]==0)
	{
		visit(i+1,j);
	}
	if(iMaze[i][j-1]==0)
	{
		visit(i,j-1);
	}
	if(iMaze[i-1][j]==0)
	{
		visit(i-1,j);
	}
	iMaze[i][j] = 0;
}

int main(int argc,char* argv[])
{
	/*init();
	process();
	DFS(iBegX,iBegY);
	if(isSuccess)
	{
		printf("\n从起点(%d,%d)可以到达终点(%d,%d)\n",iBegX,iBegY,iEndX,iEndY);
	}
	else
	{
		printf("\n从起点(%d,%d)不能到达终点(%d,%d)\n",iBegX,iBegY,iEndX,iEndY);
	}*/
	visit(startI,startJ);
	system("pause");
	getchar();
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值