AcWing 188. 武士风度的牛(BFS,C++)

AcWing 188. 武士风度的牛

题意

从一个起点遵循某种特殊规则走到终点,求最短的步数

分析

很显然,这题是bfs思想的应用。
1.首先输入数据,并在每次输入数据时判断起点和终点的坐标。
2.初始化队列,从起点开始按照规则进行遍历。规则是按照中国象棋马的走法,马在上下左右这四个基本方向上可以再往两个斜边走
3.每次遍历坐标都要检查坐标是否合法,是否是障碍,是否之前被遍历过(因为这题是从中心向四周扩散,如果当前坐标已被标记了,那么就说明路径往回走了,就说明走重复了,也就说明不是最短路)
4.对坐标进行应有的操作,在这道题中,是对原来坐标可以走的步数+1,并判断是否找到终点
PS: 这题有个巨坑,输入数据的第一个竟然是列数!!!

代码

#include 
#include 
#include 
#include 

using namespace std;
typedef pair<int,int> PII;

int n, m;//n为行数,m为列数

//dx和dy是偏移量数组
int dx[] = {-2, -2, 2, 2, -1, -1, 1, 1};
int dy[] = {-1, 1, -1, 1, -2, 2, -2, 2};

//g为地图数组
char g[155][155];

//q为进行广度优先搜索的队列
queue<PII> q;

//d数组记录了从起点到当前点走过的步数
int d[155][155];

int ans;

void bfs(PII start, PII end) {
    q.push(start);//将起始位置入队
    memset(d, -1, sizeof d);
    d[start.first][start.second] = 0;
    
    //只要队列不为空
    while (q.size()) {
        PII t = q.front();//取出队头
        q.pop();         //队头出队
        //如果当前位置就是终点位置,则输出最小步数且结束程序
        if (t == end){
            cout << d[t.first][t.second];
            return;
        }
        //遍历当前位置的8个可能走向
        for (int i = 0; i < 8; i++) {
            int x = t.first + dx[i], y = t.second + dy[i];
            if (x < 0 || x >= n || y < 0 || y >= m || g[x][y] == '*' || d[x][y] != -1)
                   continue;
            //符合条件,则当前位置入队
            q.push({x, y});
            d[x][y] = d[t.first][t.second] + 1 ;
        }
    }
}
int main() {
    cin >> m >> n;
    //start为牛的起始位置,end是草的位置
    PII start, end;
    
    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++) {
            scanf(" %c", &g[i][j]);
            if (g[i][j] == 'K') start = {i, j};
            if (g[i][j] == 'H') end = {i, j};
        }
    bfs(start, end);
    return 0;
}

你可能感兴趣的:(搜索,bfs,队列,c++)