广搜主要用到队列知识,首先把起点入队,对起点扩展找所有可以到达的下一点入队,起点分析完毕,出队,然后继续访问当前队首的点,找出队首可以到达的下一点入队,队首出队,如此循环,直到找到终点,此点即为最先到达的点。
#include<algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int M = 100+10;
char map[M][M]; //用数组记录图
bool vis[M][M]; //标记数组
int sx,sy,m,n; //初始坐标(sx,sy),图有m行n列
int dir[4][2]={-1,0,1,0,0,-1,0,1}; //方向向量
struct node
{
int x,y; //该状态坐标
int time; //到该坐标所用最短时间
};
bool judge(int x,int y) //判断坐标是否满足条件
{
if(x < m && x >= 0 && y < n && y >= 0 && !map[x][y]....) //约束条件
return 1;
return 0;
}
int bfs(int x,int y)
{
node now,next; //定义当前状态及下一状态
queue<node>q; //q队列
now.x = x, now.y = y, now.time = 0; //now初始化为起点坐标,时间为0
q.push(now); //当前状态入队
vis[x][y] = 1; //标记起点
while(!q.empty()) //若队列非空,循环,直到找到终点; 若为空仍不是终点,无解退出
{
now = q.front(); //对队首元素经行扩展
q.pop(); //队首元素出队
if(map[now.x][now.y] == 'END') //若为终点,完成任务,返回所用时间
return now.time;
for(int i = 0; i < 4; i++) //如果不是终点,分别对四周访问
{
next.x = now.x + dir[i][0];
next.y = now.y + dir[i][1];
if(judge(next.x,next.y)) //如果下一点可以走
{
vis[next.x][next.y] = 1; //标记
next.time = now.time + 1; //走了一步,时间加1
q.push(next); //下一个状态入队
}
}
}
return -1; //队列为空仍没找到终点,没完成任务,返回-1
}
int main()
{
while(cin >> m >> n)//输入图,有m行,n列
{
memset(vis,0,sizeof(vis)); //标记数组初始化
for(int i = 0; i < m; i++) //依次输入0~m-1行
{
cin >> map[i]; //输入第i行
for(int j = 0; j < n; j++)
{
if(map[i][j] == 'START') //如果坐标(i,j)是起点
{
sx = i; sy = j; //记录起点坐标
}
}
}
cout << bfs(sx,sy) << endl;//输出最少所用时间
}
return 0;
}