SY 개발일지
article thumbnail

문제 링크: https://www.acmicpc.net/problem/17090

 

문제

크기가 N×M인 미로가 있고, 미로는 크기가 1×1인 칸으로 나누어져 있다. 미로의 각 칸에는 문자가 하나 적혀있는데, 적혀있는 문자에 따라서 다른 칸으로 이동할 수 있다.

어떤 칸(r, c)에 적힌 문자가

  • U인 경우에는 (r-1, c)로 이동해야 한다.
  • R인 경우에는 (r, c+1)로 이동해야 한다.
  • D인 경우에는 (r+1, c)로 이동해야 한다.
  • L인 경우에는 (r, c-1)로 이동해야 한다.

미로에서 탈출 가능한 칸의 수를 계산해보자. 탈출 가능한 칸이란, 그 칸에서 이동을 시작해서 칸에 적힌대로 이동했을 때, 미로의 경계 밖으로 이동하게 되는 칸을 의미한다.

 

입력

첫째 줄에 미로의 크기 N, M(3 ≤ N, M ≤ 500)이 주어진다. 둘째 줄부터 N개의 줄에는 미로의 각 칸에 적힌 문자가 주어진다.

 

출력

첫째 줄에 탈출 가능한 칸의 수를 출력한다.

풀이

접근법

  1. 입력이 문자니까 우선 숫자로 치환해야겠다.
  2. 각 칸 당 경로가 하나밖에 존재하지 않으니까 dfs를 이용하여 풀자
  3. 만약 다음에 갈 칸이 경계 밖이면 탈출 가능하니까 true로 두고, 재귀를 이용해서 해당 경로까지 가는 데에 거쳤던 모든 곳을 true로 하자
  4. 이미 방문했던 곳을 또 방문하는 거면 그 칸이 갈 수 있는지, 없는지를 넘겨주자

 

코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {
    private static int N, M;
    private static int[][] arr;
    private static boolean[][] visited, dp;
    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());
        arr = new int[N][M];
        
        // 1. 입력이 문자니까 우선 숫자로 치환해야겠다.
        for(int i=0;i<N;i++) {
            String str = br.readLine();
            for(int j=0;j<M;j++) {
                switch (str.charAt(j)) {
                    case 'U':
                        arr[i][j] = 0;
                        break;
                    case 'R':
                        arr[i][j] = 1;
                        break;
                    case 'D':
                        arr[i][j] = 2;
                        break;
                    case 'L':
                        arr[i][j] = 3;
                        break;
                }
            }
        }
        dp = new boolean[N][M];
        visited = new boolean[N][M];
        for(int i=0;i<N;i++) {
            for(int j=0;j<M;j++) {
                if (visited[i][j]) continue;
                // 2. 각 칸 당 경로가 하나밖에 존재하지 않으니까 dfs를 이용하여 풀자
                dfs(i, j);
            }
        }
        int ans = 0;
        for(int i=0;i<N;i++) {
            for(int j=0;j<M;j++) if (dp[i][j]) ans++;
        }
        System.out.println(ans);
    }
    private static int[] dx = new int[]{-1, 0, 1, 0};
    private static int[] dy = new int[]{0, 1, 0, -1};
    private static boolean dfs(int x, int y) {
    
    	// 4. 이미 방문했던 곳을 또 방문하는 거면 그 칸이 갈 수 있는지, 없는지를 넘겨주자
        if (visited[x][y]) return dp[x][y];

        visited[x][y] = true;

        int nx = x + dx[arr[x][y]];
        int ny = y + dy[arr[x][y]];
        
        // 3. 만약 다음에 갈 칸이 경계 밖이면 탈출 가능하니까 true로 두고, 
        // 재귀를 이용해서 해당 경로까지 가는 데에 거쳤던 모든 곳을 true로 하자
        if (nx < 0 || nx >= N || ny < 0 || ny >= M) {
            dp[x][y] = true;
        } else {
            dp[x][y] = dfs(nx, ny);
        }
        return dp[x][y];
    }
}

 

profile

SY 개발일지

@SY 키키

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!