baekjoon/Implementation
백준 14503번 : 로봇 청소기 [자바]
Meluu_
2025. 7. 21. 09:37
🧫 문제 분석
✔️ 출처
📖 문제

구현문제
BFS를 활용하여 풀었다.
문제가 좀 이해가 안될 수 있는데
- 현재 칸이 아직 청소되지 않은 경우 청소
- 현재 칸의 주변 4칸 모두 청소되었다면
- 바라보는 방향 유지한 채 한칸 후진 가능시 후진
- 후진한 곳이 벽이면 작동 종료 (청소끝)
- 현재 칸의 주변 4칸중 하나라도 청소안되어있다면
- 반시계 방향 90도 회전
- 회전 후 바라보는 앞쪽칸이 청소되지 않았다면 한칸 전진 후 1번으로
- 아니라면 다시 90도 회전
이렇게 나뉜다.
이것만 잘 이해하면 아주 쉽게 풀 수 있는 문제였다.
🔅 문제 풀이
import java.io.*;
import java.util.*;
public class Main {
// 14503번 로봇 청소기
static int N, M;
// 북 동 남 서
static int[] dr = {-1, 0, 1, 0};
static int[] dc = {0, 1, 0, -1};
static int[][] map;
static boolean[][] visited;
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());
st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
map = new int[N][M];
visited = new boolean[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
map[i][j] = Integer.parseInt(st.nextToken());
if (map[i][j] == 1) {
visited[i][j] = true;
}
}
}
System.out.println(bfs(r,c,d));
}
private static int bfs(int r, int c, int d) {
Queue<int[]> q = new LinkedList<>();
q.add(new int[]{r, c, d});
int cnt = 0;
while (!q.isEmpty()) {
int[] cur = q.poll();
int curR = cur[0];
int curC = cur[1];
int curD = cur[2];
// 현재 칸 청소 (안되어있다면)
if (!visited[curR][curC]) {
visited[curR][curC] = true;
cnt++;
}
// 4방향 체크
int cleanRoomCnt = 0;
for (int i = 0; i < 4; i++) {
int nextR = curR + dr[i];
int nextC = curC + dc[i];
if (visited[nextR][nextC]) {
cleanRoomCnt++;
}
}
// 전부 청소되어있다면 후진 가능한지 (불가능시 청소 종료)
if (cleanRoomCnt == 4) {
int dir = getDirection(curD, true);
int backR = curR + dr[dir];
int backC = curC + dc[dir];
// 후진한 곳이 벽이라면 종료
if (map[backR][backC] == 1) {
return cnt;
}
// 원래 바라보던 방향을 유지한채로 후진
q.offer(new int[]{backR, backC, curD});
// 청소되지 않은 곳이 있다면 반시계방향 90도 회전 후 전진
} else {
int dir = getDirection(curD, false);
int newR = curR + dr[dir];
int newC = curC + dc[dir];
// 90도 회전 후 청소하지 않았다면 이동
if (!visited[newR][newC]) {
q.offer(new int[]{newR, newC, dir});
// 회전한 곳이 청소되어있다면 다시 90도 회전하기위해 큐에 삽입
} else {
q.offer(new int[]{curR, curC, dir});
}
}
}
return cnt;
}
private static int getDirection(int d, boolean isBack) {
if (isBack) {
return (d + 2) % 4;
}
return (d - 1 + 4) % 4;
}
}