문제 링크: 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개의 줄에는 미로의 각 칸에 적힌 문자가 주어진다.
출력
첫째 줄에 탈출 가능한 칸의 수를 출력한다.
풀이
접근법
- 입력이 문자니까 우선 숫자로 치환해야겠다.
- 각 칸 당 경로가 하나밖에 존재하지 않으니까 dfs를 이용하여 풀자
- 만약 다음에 갈 칸이 경계 밖이면 탈출 가능하니까 true로 두고, 재귀를 이용해서 해당 경로까지 가는 데에 거쳤던 모든 곳을 true로 하자
- 이미 방문했던 곳을 또 방문하는 거면 그 칸이 갈 수 있는지, 없는지를 넘겨주자
코드
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];
}
}
'Java > 문제풀이' 카테고리의 다른 글
[백준 17490] 일감호에 다리 놓기 - Java 문제풀이 (0) | 2024.05.07 |
---|---|
[백준 14461] 소가 길을 건너간 이유 - Java 문제풀이 (0) | 2024.05.05 |
[백준 20952] 게임 개발자 승희 - Java 문제풀이 (0) | 2024.05.02 |
[백준 22953] 도도의 음식 준비 - Java 문제풀이 (2) | 2024.04.30 |
[백준 26009] 험난한 등굣길 - Java 문제풀이 (0) | 2024.04.29 |