1. 程式人生 > 其它 >P1825 玉米田迷宮題解

P1825 玉米田迷宮題解

題目傳送門

#include <bits/stdc++.h>

using namespace std;

int n, m;
const int N = 310;
//地圖
char a[N][N];
int x, y; //Bessie的起始點
//是不是訪問過了
int st[N][N];

//放入佇列的結構體
struct node {
    int x, y, step;
};
queue<node> q; //佇列

int dx[] = {0, 0, -1, 1}; //左右上下
int dy[] = {-1, 1, 0, 0};

//找到相對點
void getDui(int x, int y, int &x1, int &y1) {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++)
            //注意不能與原點相同
            if (!(i == x && j == y) && a[i][j] == a[x][y]) x1 = i, y1 = j;
    }
}

void bfs() {
    /**
     被填充為玉米的格子用“#”表示,草地用“.”表示,每一對裝置的結點由相同的大寫字母組成“A-Z”,
     且沒有兩個不同裝置的結點用同一個字母表示,出口用“=”表示。
     */
    st[x][y] = 1;            //Bessie的起始點要設定為已使用
    q.push({x, y, 0});//初始化佇列
    //開始廣度優先搜尋
    while (!q.empty()) {
        node p = q.front();
        q.pop();
        //四個方向
        for (int i = 0; i < 4; i++) {
            //下一步的座標
            int x1 = p.x + dx[i], y1 = p.y + dy[i];

            //如果下一跳是出口
            if (a[x1][y1] == '=') {
                cout << p.step + 1 << endl;
                return;
            }
            //每一對裝置的結點由相同的大寫字母組成“A-Z”
            if (a[x1][y1] >= 'A' && a[x1][y1] <= 'Z') {
                //坐上直達飛行裝置
                //找對應的點
                getDui(x1, y1, x, y);
                x1 = x, y1 = y;
            }
            //草地用“.”表示,玉米用“#”表示
            if (x1 >= 1 && y1 >= 1 && a[x1][y1] != '#' && !st[x1][y1]) {
                q.push({x1, y1, p.step + 1});
                //標識走過了
                st[x1][y1] = 1;
            }
        }
    }
}

int main() {
    //輸入
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= m; j++) {
            cin >> a[i][j];
            if (a[i][j] == '@') x = i, y = j;//出發點
        }

    //廣度優先搜尋
    bfs();
    return 0;
}