#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;
}
笔试题:03年_迷宫
最新推荐文章于 2020-09-18 09:59:55 发布