[알고리즘 문제해결] 방문(BFS)

방문하다

원본 제목 설명

이제 도시의 특정 상인을 방문하기 위해 회사에서 출발해야 ​​하는 도시 판매 관리자가 있으며 그의 위치와 상인의 위치는 알려져 있지만 도시의 도로 교통으로 인해 그는 다음 중 하나만 선택할 수 있습니다. 움직일 때마다 좌우로 방향을 정하거나 상하에서 방향을 선택하고 이제 사업장 주소까지 가는 최단 경로가 몇 개인지 물어보세요.

지도 CityMap과 행 길이 n, 열 길이 m을 가정할 때 1은 관리자 위치, 2는 상인 위치, -1은 지나갈 수 없는 지역, 0은 지나갈 수 있는 지역을 의미하므로 숫자를 반환해주세요. 합법적인 경로가 존재하는지 확인하기 위한 솔루션입니다. 행렬의 길이와 너비가 10보다 작거나 같은지 확인하세요.

참고: 모든 솔루션의 거리가 최단 솔루션인지 확인해야 합니다.

데이터 범위: 2 ≤ n , m ≤ 10 2 \leq n,m \leq 102,10

예를 들어 입력이 [[2,0,0,0],[0,-1,-1,0],[0,-1,1,0],[0,0,0,0]인 경우 ],4 ,4시간에 해당하는 4행 4열 CityMap은 아래와 같습니다.

img

관리자의 위치는 (2,2)이고 판매자의 위치는 (0,0)입니다. 분석 결과 관리자가 판매자 주소에 도달하는 가장 짧은 방법은 두 가지가 있습니다.

(2,2)->(2,3)->(1,3)->(0,3)->(0,2)->(0,1)->(0,0)

그리고

(2,2)->(3,2)->(3,1)->(3,0)->(2,0)->(1,0)->(0,0), 따라서 해당 반환 값은 2입니다.

실시예 1

입력하다:

[[0,1,0],[2,0,0]],2,3

반환 값:

2

실시예 2

입력하다:

[[2,0,0,0],[0,-1,-1,0],[0,-1,1,0],[0,0,0,0]],4,4

반환 값:

2

BFS

  • BFS는 최단 경로 검색을 수행할 수 있으며 , 이를 기반으로 이 질문을 약간 수정했습니다.

  • 통과한 노드 표시 - 1 -11이면 반복 순회를 방지하지만 중간점을 표시할 필요가 없습니다. 그렇지 않으면 두 번째 도착점을 끝점으로 인식할 수 없습니다.

  • min_dis최단 거리를 기록하고 min_cnt최단 경로가 몇 개 있는지 기록하는 데 사용합니다.

  • 구조체는 TII맵 포인트 좌표와 시작점에서 포인트까지의 거리를 정의하고, 이를 기준으로 인접한 노드는 +1이 됩니다.

  • 경계를 넘는지 확인하려면 다음 노드의 위치에 주의하세요.

#include <bits/stdc++.h>

#define debug

#define x first
#define y second
using namespace std;

struct TII {
    int x, y, dis;
};

int countPath(vector<vector<int> > &CityMap, int n, int m) {
 	queue<TII> q;
    int dx[] = {0, -1, 0, 1}, dy[] = {-1, 0, 1, 0};
    //找起点
    TII st;
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            if (CityMap[i][j] == 1) {
                st = {i, j, 0};
                break;
            }
        }
    }
    //BFS搜索
    q.push(st);
    CityMap[st.x][st.y] = -1;
    int min_dis = 0x3f3f3f3f;
    int min_cnt = 0;

    while (!q.empty()) {
        TII tmp = q.front();
        q.pop();
        cout << tmp.x << ' ' << tmp.y << endl;
        if (CityMap[tmp.x][tmp.y] == 2) {
            if (tmp.dis < min_dis) {
                min_cnt = 1;
                min_dis = tmp.dis;
            } else if (tmp.dis == min_dis) { min_cnt++; }
        } else {
            CityMap[tmp.x][tmp.y] = -1;//标记已经走过,终点不能标记,否则第二次到达无法判断
            //将邻接的点加入队列
            for (int i = 0; i < 4; ++i) {
                int xi = tmp.x + dx[i], yi = tmp.y + dy[i];
                if (xi < 0 || xi >= n || yi < 0 | yi >= m)continue;
                if (CityMap[xi][yi] != -1) {
                    q.push({xi, yi, tmp.dis + 1});
                }
            }
        }
    }
    return min_cnt;
}
int main() {
#ifdef debug
    freopen("in.txt", "r", stdin);
#endif
    ios::sync_with_stdio(0);
    int n, m;
    cin >> n >> m;
    vector<vector<int>> g(n, vector<int>(m));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < m; ++j) {
            cin >> g[i][j];
        }
    }
    cout << '@' << countPath(g, n, m) << endl;
    return 0;
}

추천

출처blog.csdn.net/u011459717/article/details/128613646