문제 링크

  • 내 풀이

큐의 원소에 벽을 파괴 여부를 판단하는 요소를 추가한다. 일단 벽을 만나면 한번 파괴한 후 파괴 했음을 표기한다. 벽을 파괴한 전용 체크 리스트도 이용한다. 왜냐하면 체크리스트를 공유하면 한겹벽인 꼬불꼬불한 길에서 선행된 파괴하며 진행한 탐색과 겹쳐져 제대로 탐색하지 못하는 경우가 생기기 때문이다.

#include <iostream>
#include <cstring>
#include <queue>

using namespace std;

constexpr int dr[4] = { -1, 1, 0, 0 };
constexpr int dc[4] = { 0, 0, -1, 1 };

int chk[2][1000][1000];
int m[1000][1000];
int N, M;

struct pos {
    int r, c, isBrk, dis;
};

int bfs()
{
    queue<pos> q;
    
    q.push({ 0, 0, 0, 1 });
    chk[0][0][0] = 1;

    while (!q.empty())
    {
        int r = q.front().r;
        int c = q.front().c;
        int ib = q.front().isBrk;
        int dis = q.front().dis;
        q.pop();

        if (r == N - 1 && c == M - 1)
            return dis;

        for (int d = 0; d < 4; d++)
        {
            int nr = r + dr[d];
            int nc = c + dc[d];

            if (nr < 0 || nr >= N || nc < 0 || nc >= M || chk[ib][nr][nc] || (ib && chk[!ib][nr][nc]))
                continue;

            if (m[nr][nc])
            {
                if (!ib)
                {
                    q.push({ nr, nc, 1, dis + 1 });
                    chk[ib][nr][nc] = 1;
                }
            }
            else
            {
                q.push({ nr, nc, ib, dis + 1 });
                chk[ib][nr][nc] = 1;
            }
        }
    }

    return -1;
}

int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(0);

    string tmp;

    cin >> N >> M;

    for (int r = 0; r < N; r++)
    {
        cin >> tmp;
        for (int c = 0; c < M; c++)
        {
            m[r][c] = tmp[c] - '0';
        }
    }

    cout << bfs() << "\n";
}
  • 다른 사람 풀이

(0,0)에서 출발하고 도착지에서 출발하여 벽까지 진행한 다음 둘의 합의 최소값을 반환한다.

#include<iostream>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int, int> p;
const int INF = 987654321;
char a[1000][1000];
int N, M;
queue<p> q;
int dist[1000][1000];
int rdist[1000][1000];
int dx[] = { 1, -1 ,0 ,0 };
int dy[] = { 0, 0 ,1 ,-1 };

bool check(int r, int c) {
    if (r < 0 || r >= N || c < 0 || c >= M) return false;
    return true;
}

void bfs() {
    q.push({ 0,0 });
    dist[0][0] = 0;
    while (!q.empty()) {
        int r = q.front().first;
        int c = q.front().second;
        q.pop();
        if (a[r][c] == '1') continue;
        for (int k = 0; k < 4; ++k) {
            int nr = r + dx[k];
            int nc = c + dy[k];
            if (check(nr, nc) && dist[nr][nc] == -1) {
                q.push({ nr,nc });
                dist[nr][nc] = dist[r][c] + 1;
            }
        }
    }
}

void rbfs() {
    q.push({ N-1,M-1 });
    rdist[N-1][M-1] = 0;
    while (!q.empty()) {
        int r = q.front().first;
        int c = q.front().second;
        q.pop();
        if (a[r][c] == '1') continue;
        for (int k = 0; k < 4; ++k) {
            int nr = r + dx[k];
            int nc = c + dy[k];
            if (check(nr, nc) && rdist[nr][nc] == -1) {
                q.push({ nr,nc });
                rdist[nr][nc] = rdist[r][c] + 1;
            }
        }
    }
}

int main() {
    ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
    cin >> N >> M;
    memset(dist, -1, sizeof(dist));
    memset(rdist, -1, sizeof(rdist));
    for (int i = 0; i < N; ++i) {
        cin >> a[i];
    }
    bfs();
    rbfs();
    int ans = INF;
    for (int i = 0; i < N; ++i) {
        for (int j = 0; j < M; ++j) {
            if (dist[i][j] != -1 && rdist[i][j] != -1)
                ans = min(ans, dist[i][j] + rdist[i][j]);
        }
    }
    if(ans != INF)
        cout << ans+1 << "\n";
    else cout << "-1\n";

    return 0;
}

댓글남기기