기억보다는 기록을 해볼까

[백준 2206] 벽 부수고 이동하기 (C++) - 48 본문

백준으로 C++ 공부하기

[백준 2206] 벽 부수고 이동하기 (C++) - 48

옥상에서 2022. 1. 13. 00:04
728x90

문제

https://www.acmicpc.net/problem/2206

 

2206번: 벽 부수고 이동하기

N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로

www.acmicpc.net

생각

원래 생각

벽이 있는 칸을 저장을 한 후 그곳들을 순회하여 하나씩 없애보면서 탐색을 실시한다.

이 생각으로 풀었더니 시간초과로 두들겨 맞았다.

 

다음 생각

벽을 뚫었는지 안뚫었는지를 저장을 해놓으면서 탐색을 실시한다.

코드

원래 생각

#include <iostream>
#include <queue>
#include <vector>
#include <string>
#include <string.h>
using namespace std;

int n, m;
string map[1001];
int tmp[1001][1001];
bool vst[1001][1001];
vector<pair<int, int>> v;
int dy[4] = {0, 1, 0, -1};
int dx[4] = {1, 0, -1, 0};
const int INF = 987654321;
int mini = INF;
int cost;

void init() {
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < m; j++) tmp[i][j] = map[i][j] - '0';
    }
    return;
}

void search() {
    queue<pair<pair<int, int>, int>> q;
    q.push({{0, 0}, 0});
    while(!q.empty()) {
        auto[cy, cx] = q.front().first;
        cost = q.front().second;

        if(cost > mini) return;
        //찾았다!
        if(cy == n - 1 && cx == m - 1) {
            if(mini > cost) {
                mini = cost;
            }
        }
        q.pop();

        for(int j = 0; j < 4; j++) {
            int ny, nx;
            ny = cy + dy[j];
            nx = cx + dx[j];

            if(ny < 0 || nx < 0 || ny > n - 1 || nx > m - 1) continue;
            if(vst[ny][nx] || tmp[ny][nx] == 1) continue;

            q.push({{ny, nx}, cost + 1});
            vst[ny][nx] = true;
        }
    }
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie();
	std::cout.tie();
    cin >> n >> m;
    for(int i = 0; i < n; i++) {
        cin >> map[i];
        for(int j = 0; j < m; j++) {
            tmp[i][j] = map[i][j] - '0';
            if(tmp[i][j] == 1) v.push_back({i, j});
        }
    }

    for(int i = 0; i < v.size(); i++) {
        int wy, wx;
        wy = v[i].first;
        wx = v[i].second;
        int cost;
        init();
        memset(vst, false, sizeof(vst));

        tmp[wy][wx] = 0;
        search();
    }
    if(v.size() == 0) {
        search();
        if(mini == INF) cout << "-1";
        else cout << mini + 1;
    }

    if(mini == INF) cout << "-1";
    else cout << mini + 1;
}

다음 생각

#include <iostream>
#include <queue>
#include <vector>
#include <string>
using namespace std;

int n, m;
int map[1001][1001];
bool vst[1001][1001][2];
vector<pair<int, int>> v;
int dy[4] = {0, 1, 0, -1};
int dx[4] = {1, 0, -1, 0};
int block, cost, ans;

int search() {
    queue<pair<pair<int, int>,pair<int, int>>> q;
    q.push({{0, 0}, {0, 1}});
    vst[0][0][0] = true;
    while(!q.empty()) {
        auto[cy, cx] = q.front().first;
        auto[block, cost] = q.front().second;
        q.pop();

        if(cy == n - 1 && cx == m - 1) {
            return cost;
        }

        for(int j = 0; j < 4; j++) {
            int ny, nx;
            ny = cy + dy[j];
            nx = cx + dx[j];

            if(ny < 0 || nx < 0 || ny > n - 1 || nx > m - 1) continue;
            //다음 칸이 1이고 아직 뿌수기를 쓰지 않았다
            if(map[ny][nx] == 1 && block == 0) {
                //뿌셔
                q.push({{ny, nx}, {block + 1, cost + 1}});
                vst[ny][nx][block + 1] = true;
            }
            //다음 칸이 0일 때
            else if(map[ny][nx] == 0 && !vst[ny][nx][block]){
                q.push({{ny, nx}, {block, cost + 1}});
                vst[ny][nx][block] = true;
            }
        }
    }
    return -1;
}

int main() {
	std::ios::sync_with_stdio(false);
	std::cin.tie();
	std::cout.tie();
    cin >> n >> m;
    string str;
    for(int i = 0; i < n; i++) {
        cin >> str;
        for(int j = 0; j < m; j++) {
            map[i][j] = str[j] - '0';
        }
    }

    cout << search();
}
728x90
Comments