anott
기록
anott
  • 분류 전체보기
    • 오라클
    • SQL
    • 알고리즘
      • 백준저지
      • 프로그래머스
      • SWEA
    • 개발 관련
    • 프론트엔드
      • TypeScript, Next.js
      • React 공식문서 읽기
hELLO · Designed By 정상우.
anott

기록

백준저지 2206번 벽 부수고 이동하기 (Java)
알고리즘/백준저지

백준저지 2206번 벽 부수고 이동하기 (Java)

2021. 10. 4. 23:55

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

 

2206번: 벽 부수고 이동하기

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

www.acmicpc.net

 

 

접근 방법

시작점부터 BFS로 4방 탐색을 진행한다.

boolean 타입의 3차원 배열을 만들어서 벽을 부쉈는지 여부를 체크한다.

이동할 수 있는 곳(0)은 그냥 이동하고, 벽(1)을 만나면 현재 벽을 부순 상태인지 확인해서 그렇지 않은 경우만 이동한다. 이때, 벽을 아직 안 부순 현 상태를 true로 체크하고, 벽을 부순 자리를 큐에 넣는다.

 

 

 

생각

벽을 부술 때 부순 곳을 방문했다고 체크했어도 문제가 통과되고, 부수지 않은 부수기 직전의 상태를 방문했다고 체크해도 똑같이 통과가 된다. 다만 시간 차이 때문에 후자를 하는 것이 맞는 것 같다.

 

 

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class BOJ2206 {
    static int N, M, map[][];

    static private class Position {
        int x, y, wall, cnt; // x좌표, y좌표, 벽 부쉈는지 여부(0 또는 1), 이동 거리

        public Position(int x, int y, int wall, int cnt) {
            this.x = x;
            this.y = y;
            this.wall = wall;
            this.cnt = cnt;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());
        M = Integer.parseInt(st.nextToken());
        map = new int[N][M];
        for (int i = 0; i < N; i++) {
            char[] input = br.readLine().toCharArray();
            for (int j = 0; j < M; j++) {
                map[i][j] = input[j] - '0';
            }
        }

        System.out.println(move());
    }

    private static int move() { // bfs
        int[][] d = { { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } };
        boolean[][][] visited = new boolean[2][N][M]; // 방문 여부 체크. 0은 벽 안 부쉈고, 1은 벽 부수고 이동

        Queue<Position> q = new LinkedList<>();
        q.add(new Position(0, 0, 0, 1)); // 시작
        visited[0][0][0] = true;

        while (!q.isEmpty()) {
            Position cur = q.poll();

            if (cur.x == N - 1 && cur.y == M - 1) { // 종료 조건
                return cur.cnt;
            }

            for (int i = 0; i < 4; i++) {
                int dx = cur.x + d[i][0];
                int dy = cur.y + d[i][1];
                int cnt = cur.cnt;
                int wall = cur.wall;
                if (dx < 0 || dx >= N || dy < 0 || dy >= M || visited[wall][dx][dy]) {
                    continue;
                }
                if (map[dx][dy] == 0) { // 0이라면 그냥 이동
                    visited[wall][dx][dy] = true;
                    q.add(new Position(dx, dy, wall, cnt + 1));
                } else if (map[dx][dy] == 1 && wall == 0) { // 1이라면 벽을 부수지 않은 경우만 이동
                    visited[wall][dx][dy] = true;
                    q.add(new Position(dx, dy, wall + 1, cnt + 1));
                }
            }
        }

        return -1; // 이동 불가능
    }
}

 

저작자표시 비영리 (새창열림)

'알고리즘 > 백준저지' 카테고리의 다른 글

백준저지 1747번 소수&팰린드롬  (0) 2021.10.06
백준저지 14442번 벽 부수고 이동하기 2 (Java)  (0) 2021.10.05
백준저지 1755번 숫자놀이  (0) 2021.09.27
백준저지 14502번 연구소  (0) 2021.09.26
백준저지 2667번 단지번호붙이기  (0) 2021.09.20
    '알고리즘/백준저지' 카테고리의 다른 글
    • 백준저지 1747번 소수&팰린드롬
    • 백준저지 14442번 벽 부수고 이동하기 2 (Java)
    • 백준저지 1755번 숫자놀이
    • 백준저지 14502번 연구소
    anott
    anott

    티스토리툴바