题目:
定义一个二维数组:
int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, };
它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的最短路线。
输入:
0 1 0 0 0
0 1 0 1 0
0 0 0 0 0
0 1 1 1 0
0 0 0 1 0
输出:
(0, 0)
(1, 0)
(2, 0)
(2, 1)
(2, 2)
(2, 3)
(2, 4)
(3, 4)
(4, 4)
这个题思维很不错,对于我这种代码实现能力较弱的人来说即使有着明确的思路但是实现过程中还是充满坎坷的。
这个题数据很水,只有样例一个数据,也就是说你直接输出样例就能过。但是我们写题还是主要看题目意义,按照题目要求解题就好。
废话不多说:
看到二维地图+起点+终点+最短路径,直接想到BFS
上代码:
#include<iostream>
#include<algorithm>
#include<queue>
#include<utility>
#include<cstring>
using namespace std;
const int N=1e4;
int n,m;
int a[6][6],vis[6][6];//因为题目数据很水,5,5就够用了,按实际情况调整
int dx[4]={-1,1,0,0};
int dy[4]={0,0,1,-1};
//二维数组广搜的4个方向
struct Node{//结构体表示一个点
int x,y;
}pre[100][100];//pre用来记录深搜的父亲(原理类似链式前向星建边遍历的索引)
void BFS(int x,int y){//开始广搜
queue<Node>q;
Node st;
st.x=x;
st.y=y;
q.push(st);//定义起点并将起点入队
while(q.size()){
Node v,u;
v=q.front();
q.pop();
if(v.x==n-1&&v.y==m-1){//走到终点了,就结束了,因为广搜有着只要第一个找到就是最短的特性
break;
}
for(int i=0;i<4;i++){
int tx=v.x+dx[i];
int ty=v.y+dy[i];//开始尝试移动
if(tx<0||tx>=5||ty<0||ty>=5||vis[tx][ty]||a[tx][ty])//如果越界、为石头、走过了,都不满足题意,舍弃
continue;
vis[tx][ty]=1;//没有被淘汰的都满足题意,标记为走过
u.x=tx;
u.y=ty;
q.push(u);//新点入队
pre[tx][ty]=v;//记录我是从哪个点进入这个点的(父亲)
}
}
}
void My_out(Node u){//这个输出方法其实挺有意思,采用递归方式完美的解决了路径问题
if(u.x==0&&u.y==0){
printf("(%d, %d)\n",u.x,u.y);
return;
}
My_out(pre[u.x][u.y]);
printf("(%d, %d)\n",u.x,u.y);//从终点开始一直往父亲递归,pre[x][y]记录的就是(x,y)这个点的父亲是哪个点,就这样一直递归到起点,开始return回来依次输出
}
int main(){
n=m=5;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin >> a[i][j];
}
}
BFS(0,0);
Node tmp;
tmp.x=n-1;
tmp.y=m-1;
My_out(tmp); //从终点开始进入输出函数
return 0;
}
写得比较粗糙,算是我的个人笔记吧,我确实觉得这个题的路径输出问题很有意思。