您的位置:首页 > 其它

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

2015-12-19 16:18 281 查看
老鼠走迷宫

问题描述

老鼠走迷宫是递回求解的基本题型,

试以程式求出由入口至出口的路径,入口为左上角,出口为右下角。

迷宫图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

={ 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

; /* 标记 */
/* 为了找出最短路径 */
struct node
{
int step;       /* 所用步数 */
int ans

;  /* 一种路径 */
}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

={0};  //标记是否已经扩展
//迷宫初始化
int Map

={ 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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: