[2206πŸ‘] λ²½ λΆ€μˆ˜κ³  μ΄λ™ν•˜κΈ°

!Β·2022λ…„ 7μ›” 6일
0

BFS/DFS

λͺ©λ‘ 보기
16/17

λ‚΄ μ½”λ“œ

#include <iostream>
#include <queue>
#include <utility>
using namespace std;

int field[1001][1001];
int dist[1001][1001];
int xdir[4] = {1,0,-1,0};
int ydir[4] = {0,1,0,-1};
int m,n;

int main(void)
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin >> n >> m;
    for(int i = 1;i<=n;i++)
    {
        for(int j = 1;j<=m;j++)
        {
            string str; cin >> str;
            dist[i][j] = -1;
            field[i][j] = str[j-1] - '0';
        }
    }
    queue<pair<int,int>> q;
    q.push({1,1}); 
    dist[1][1] = 1;
    
    while(!q.empty())
    {
        pair<int,int> cur = q.front(); q.pop();
        int broke = 0;
        for(int i = 0;i<4;i++)
        {
            int curx = cur.first + xdir[i];
            int cury = cur.second + ydir[i];
            if(curx<1||curx>=n||cury<1||cury>=m) continue;
            if(field[curx][cury] == 1 && broke == 0)
            {
                broke++;
                field[curx][cury] = 0;
                dist[curx][cury] = dist[cur.first][cur.second] + 1;
                q.push({curx,cury});
                continue;
            }
            if(dist[curx][cury] >= 1 || field[curx][cury] == 1) continue;
            q.push({curx,cury});
            dist[curx][cury] = dist[cur.first][cur.second] + 1;
            if(curx == n && curx == m)
            {
                cout << dist[curx][cury];
                return 0;
            }
        }
    }
    cout << -1;
    
}

첫번째 μ‹œλ„μ—μ„œ μ˜€λ‹΅μ΄ λ‚˜μ˜€κ³ , λ‘λ²ˆμ§Έ μ‹œλ„μ—μ„œλŠ” μ‹œκ°„μ΄ˆκ³Όκ°€ λ‚˜μ™”λ‹€. κ²°κ³Όμ μœΌλ‘œλŠ” μ‹€νŒ¨ γ… 
첫번째 μ‹œλ„μ—μ„œλŠ” 벽을 λΆ€μ‰ˆλŠ”μ§€ μ•ˆλΆ€μ‰ˆλŠ”μ§€ μ²΄ν¬ν•˜λŠ” μ „μ—­λ³€μˆ˜λ₯Ό ν•˜λ‚˜ λ§Œλ“€μ–΄μ„œ bfs의 if λ¬Έμ—μ„œ fieldκ°€ 1 μΌλ•Œ μ „μ—­λ³€μˆ˜λ₯Ό +1 ν•˜μ—¬ κ΅¬μ„±ν•˜μ˜€μœΌλ‚˜, μ‹€νŒ¨ν–ˆλ‹€.

λ‘λ²ˆμ§Έ μ‹œλ„μ—μ„œλŠ” field 에 1 의 μœ„μΉ˜λ₯Ό deque 에 μ €μž₯ν•˜κ³  deque μ—μ„œ 뽑아 field λ₯Ό ν•˜λ‚˜μ”© 0 으둜 λ°”κΏ” bfs λ₯Ό λŒλ¦¬λ©΄μ„œ μ΅œμ†Œκ°’μ„ 찾고자 ν•˜μ˜€μœΌλ‚˜ μ‹œκ°„μ΄ˆκ³Όλ‘œ μ‹€νŒ¨ν–ˆλ‹€.


μ •λ‹΅

#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second

int dx[4] = {0,1,0,-1};
int dy[4] = {1,0,-1,0};

char board[1000][1000];
int dist[1000][1000][2];
// dist[x][y][0] : 벽을 ν•˜λ‚˜λ„ λΆ€μˆ˜μ§€ μ•Šκ³  (x,y)κΉŒμ§€ μ˜€λŠ”λ° κ±Έλ¦¬λŠ” λΉ„μš©
// dist[x][y][1] : 벽을 ν•˜λ‚˜λ§Œ λΆ€μˆ˜κ³  (x,y)κΉŒμ§€ μ˜€λŠ”λ° κ±Έλ¦¬λŠ” λΉ„μš©, (x,y)κ°€ λ²½μ΄λΌμ„œ λΆ€μˆ˜λŠ” 경우 포함
int n, m;

bool OOB(int x, int y){
  return x < 0 || x >= n || y < 0 || y >= m;
}

int bfs() {
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j)
      dist[i][j][0] = dist[i][j][1] = -1;
  dist[0][0][0] = dist[0][0][1] = 1;
  queue<tuple<int, int, int>> q;
  q.push({0,0,0});
  while (!q.empty()) {
    int x, y, broken;
    tie(x, y, broken) = q.front();
    if(x == n-1 && y == m-1) return dist[x][y][broken];
    q.pop();
    int nextdist = dist[x][y][broken] + 1;
    for (int dir = 0; dir < 4; ++dir) {
      int nx = x + dx[dir];
      int ny = y + dy[dir];
      if(OOB(nx, ny)) continue;      
      if (board[nx][ny] == '0' && dist[nx][ny][broken] == -1) {
        dist[nx][ny][broken] = nextdist;
        q.push({nx, ny, broken});
      }      
      // (nx, ny)λ₯Ό λΆ€μˆ˜λŠ” 경우
      if (!broken && board[nx][ny] == '1' && dist[nx][ny][1] == -1) {
        dist[nx][ny][1] = nextdist;
        q.push({nx, ny, 1});
      }      
    }
  }
  return -1;
}

int main(void) {
  ios::sync_with_stdio(0);
  cin.tie(0);
  cin >> n >> m;
  for (int i = 0; i < n; ++i)
    for (int j = 0; j < m; ++j)
      cin >> board[i][j];
  cout << bfs();
  return 0;
}

μ²˜μŒμ— λ³΄μ•˜μ„λ–„λŠ” 이해가 μ•ˆλ˜μ—ˆμœΌλ‚˜, ν•˜λ‚˜μ”© κ³±μ”Ήμ–΄λ³΄λ‹ˆ μ§„μ§œ κΈ°λ°œν•œ μ½”λ“œλ‹€.. γ… γ…  (μ–Έμ œ 이정도 μ‹€λ ₯이 될까)
배열을 1측이 μ•„λ‹Œ 2측으둜 μ„ μ–Έν•΄ 1μΈ΅μ—λŠ” 벽을 ν†΅κ³Όν•˜μ§€ μ•Šμ‚ 경우, 2μΈ΅μ—λŠ” ν†΅κ³Όν•œ κ²½μš°μ΄λ‹€. 즉, 1μΈ΅μ—μ„œ 움직이닀가 졜초둜 벽에 λ‹Ώμ„μ‹œ 에 2측으둜 μ˜¬λΌκ°€λŠ” 것이닀. μ—¬λŸ¬ μ°¨λ‘€ 생각해봐도 μ§„μ§œ κΉ”λ”ν•˜λ‹€....

profile
개발자 지망생

0개의 λŒ“κΈ€