【蓝桥第三周】老鼠走迷宫

老鼠走迷宫

问题描述

老鼠走迷宫是递回求解的基本题型,
试以程式求出由入口至出口的路径,入口为左上角,出口为右下角。

迷宫图7×7



墙的表示:█ 路径的表示:◇
INPUT
(无)
OUTPUT
显示迷宫:


显示路径:

解法一

[解题思路]

深度搜索,在题的基础上考虑了多种路径到达终点的状况,输出最短路径,需要注意的是a[index].ans[new_x][new_y]=0;

[代码实现]

#include<iostream>
using namespace std;
const int N=7;
/* 地图,1表示障碍 0表示可用 */
int Map[N][N]={ 1,1,1,1,1,1,1,
				1,0,0,0,0,1,1,
				1,0,1,1,1,0,1,
				1,0,1,0,0,0,1,
				1,0,1,0,1,0,1,
				1,0,0,0,1,0,1,
				1,1,1,1,1,1,1 };
int book[N][N]; /* 标记 */
/* 为了找出最短路径 */	
struct node
{
	int step;       /* 所用步数 */
	int ans[N][N];  /* 一种路径 */
}a[100];

int index=0,min_index;  /* 最少步数的下标 */
int Min=9999;           /* 最小步数 */
const int end_x=5,end_y=5;	/* 终点 */
/* 方向 */
int Next[4][2] = {{0, 1},{1, 0},{0, -1},{-1, 0}};/*右,下,左,上*/
void dfs(int x,int y,int Step)
{
	a[index].ans[1][1]=2;     /* 起点标记 */
	if(x==end_x && y==end_y)
	{
		a[index].step=Step;   /* 保存步数 */
		if(Step<Min)
		{
			Min=Step;        /* 更新 min step */
			min_index=index; /* 只要输出最小步数的路径,所以记录下来 */
		}
		index++;
		return ;
	}
	for(int i=0;i<=3;i++)
	{
		int	new_x=x+Next[i][0];
		int new_y=y+Next[i][1];
		if(new_x<1 || new_x>N-1 ||new_y<1 ||new_y>N-1)  /* 越界 */
		{
			continue;
		}
		if(book[new_x][new_y]==0 && Map[new_x][new_y]!=1) /* 没有使用过,并且没有障碍*/
		{
			book[new_x][new_y]=1;
			a[index].ans[new_x][new_y]=2;
			dfs(new_x,new_y,Step+1);
			a[index].ans[new_x][new_y]=0;
			book[new_x][new_y]=0;
		}
	}
}
void print()
{
	for(int i=0;i<N;i++)
		for(int j=0;j<N;j++)
		{
			if(Map[i][j]==0)
			{
				if(a[min_index].ans[i][j]==2)cout<<"◇";
				else cout<<"  ";
			}
			else cout<<"█";
			if(j==N-1) cout<<endl;  /* 格式控制 */
		}
	cout<<endl;
}
int main()
{
	print();
	dfs(1,1,0);
	print();
	return 0;
}
解法二

[解题思路]

   广度优先搜索,找最短路径。利用队列实现。

[代码实现]

#include<iostream>
using namespace std;
struct note
{
	int x;	//横坐标
	int y;	//纵坐标
	int f;  //父亲在队列中的编号
	int s;	//步数
}que[100];
const int N=8;

int Book[N][N]={0};  //标记是否已经扩展
//迷宫初始化
int Map[N][N]={ 0,0,0,0,0,0,0,0,
				0,1,1,1,1,1,1,1,
				0,1,0,0,0,0,1,1,
				0,1,0,1,1,1,0,1,
				0,1,0,1,0,0,0,1,
				0,1,0,1,0,1,0,1,         
				0,1,0,0,0,1,0,1,
				0,1,1,1,1,1,1,1 };
//定义一个用于表示走的方向的数组
int Next[4][2] = { {0, 1},  //右
			   {1, 0},    //下
			   {0, -1},   //左
			   {-1, 0} };  //上


int head=1;int tail=1; //队列初始化


void pfs(int start_x,int start_y,int end_x,int end_y);
void print(int start_x,int start_y);
int main()
{
	int start_x,start_y;  //开始位置
	int end_x,end_y;      //目标位置

	start_x=2;start_y=2;  //起点初始化
	end_x=6;end_y=6;      //终点初始化

	pfs(start_x,start_y,end_x,end_y);				//广度
	print(start_x,start_y);            //显示
	return 0;
	
}
void pfs(int start_x,int start_y,int end_x,int end_y)
{
	int new_x,new_y;      //扩展的x,y
	//往队列插入迷宫入口坐标
	que[tail].x=start_x;
	que[tail].y=start_y;
	que[tail].f=0;
	que[tail].s=0;
	tail++;
	Book[start_x][start_y]=1;

	int flag=0; //用来标记是否到达目标点,0表示暂时还没有到达,1表示到达

	//队列不为空循环
	while(head<tail)
	{
		//枚举4个方向 
		for(int i=0;i<4;i++)
		{
			//计算下一个点的坐标
			new_x=que[head].x+Next[i][0];
			new_y=que[head].y+Next[i][1];
			//判断是否越界
			if(new_x<1 || new_x>N-1 || new_y<1 || new_y>N-1)
			{
				continue;
			}
			//判断是否是障碍物或者已经在路径中
			if(Book[new_x][new_y]==0 && Map[new_x][new_y]==0)
			{
				//把这个点标记为已经走过
				//注意宽搜每个点只入队一次,所以和深搜不同,不需要将Book还原
				Book[new_x][new_y]=1;
				que[tail].x=new_x;
				que[tail].y=new_y;
				que[tail].f=head;		    //因为这个点是从head扩展出来的,所以它的父亲是head
				que[tail].s=que[head].s+1;  //步数是父亲的步数+1
				tail++;
			}
			if(new_x==end_x && new_y==end_y)
			{
				flag=1;
				break;
			}
		}//for循环结束
		if(flag==1)
		{
			break;
		}
		head++;
	}//while循环结束

}
void print(int start_x,int start_y)
{
	//打印队列中末尾最后一个点(目标点)的步数
	//注意tail是指向队尾(即最后一位)的下一个位置,所以这需要-1
	//printf("%d",que[tail-1].s);
	int temp=tail-1;
	//将路径标为2用于输出
	while(1)
	{
		Map[que[temp].x][que[temp].y]=2;
		temp=que[temp].f;
		if(que[temp].x==start_x && que[temp].y==start_y) //当父亲结点是起点时候结束
		{
			Map[que[temp].x][que[temp].y]=2;
			break;
		}
	}
	//打印迷宫
	for(int i=1;i<N;i++)
	{
		for(int j=1;j<N;j++)
		{
			if(Map[i][j]==1)
			{
				cout<<"█"; 
			}
			if(Map[i][j]!=1)
			{
				cout<<"  ";
			}
		}
		cout<<endl;
	}
	//打印路径
	for(int i=1;i<N;i++)
	{
		for(int j=1;j<N;j++)
		{
			if(Map[i][j]==1)
			{
				cout<<"█"; 
			}
			if(Map[i][j]==2)
			{
				cout<<"◇";
			}
			if(Map[i][j]==0)
			{
				cout<<"  ";
			}
		}
		cout<<endl;
	}
}




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值