로봇 청소기 (14503번)
사용 언어 : Java
레벨 : 골드5
📎 https://www.acmicpc.net/problem/14503
14503번: 로봇 청소기
첫째 줄에 방의 크기 $N$과 $M$이 입력된다. $(3 \le N, M \le 50)$ 둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 $(r, c)$와 처음에 로봇 청소기가 바라보는 방향 $d$가 입력된다. $d$가 $0$인 경우 북쪽
www.acmicpc.net
❓ 접근
문제를 보자마자 그동안 풀어본 BFS 문제 풀이들을 약간 바꿔서 사용하면 되겠다 생각했다.
1. 현재 칸이 청소되지 않은 경우, 현재 칸을 청소한다.
2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우
- 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
- 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우
- 반시계 방향으로 90도 회전한다.
- 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다.
- 1번으로 돌아간다.
우선 주의할 점이 있는데 주변에 4칸 중 청소되지 않은 빈 칸이 하나라도 있는 경우 무조건 반시계 방향으로 90도를 회전해야 한다. 나는 처음에 이 조건을 생각하지 않고 구현을 해서 바라보는 방향의 앞쪽 칸이 청소되지 않은 칸이면 바로 이동을 하도록 해서 예제를 틀렸었는데 이 부분을 고려하지 않았기 때문이였다.
✏️ 풀이
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class BOJ14503 {
static int N, M;
static int r, c, d, count;
static int[][] room;
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());
r = Integer.parseInt(st.nextToken()); // x 좌표
c = Integer.parseInt(st.nextToken()); // y 좌표
d = Integer.parseInt(st.nextToken()); // 방향(0 : 위, 1 : 오른쪽, 2 : 아래, 3 : 왼쪽)
room = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++) {
room[i][j] = Integer.parseInt(st.nextToken());
}
}
solution();
System.out.println(count);
}
static void solution() {
int[][] dist = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}}; // d의 방향과 동일
while (true) {
// 인접한 칸에 청소하지 않은 칸이 있는지 체크하는 변수
boolean check = false;
// 현재 칸이 청소되어 있지 않다면 청소
if (room[r][c] == 0) {
room[r][c] = 2;
count++;
}
// 인접한 칸 중 청소하지 않은 칸이 있으면 무조건 반시계 90도로 돌거기 때문에 d - 1부터 시작
for (int i = d - 1; i > d - 5; i--) {
// dist의 반대방향으로 움직일거기 때문에 i-- 해주고 배열의 크기를 벗어나지 않도록 +4 %4를 해줌
int nx = r + dist[(i + 4) % 4][0];
int ny = c + dist[(i + 4) % 4][1];
if (nx < 0 || nx >= N || ny < 0 || ny >= M) continue;
// 다음으로 이동할 위치가 이미 청소 되어있거나, 벽일 경우 다음 90도 확인
if (room[nx][ny] > 0) continue;
// 여기까지 오면 앞칸이 청소할 칸이니까 체크해주고 그 칸으로 이동해서 좌표 갱신
check = true;
r = nx;
c = ny;
// 방향도 갱신해줌
d = (i + 4) % 4;
// 더 이상 볼필요 없으니 break
break;
}
if (!check) {
// 만약 인접한 칸 중 청소할 수 있는 칸이 없을 경우
// 후진
r += dist[(d + 2) % 4][0];
c += dist[(d + 2) % 4][1];
// 배열의 크기를 벗어나거나 벽일 경우 while문 종료
if (r < 0 || r >= N || c < 0 || c >= M || room[r][c] == 1) break;
}
}
}
}

BFS 문제를 풀 수 있다면 어렵지 않게 풀 수 있는 문제였던 것 같다! 로봇이 청소할 때마다 출력을 확인해서 잘 작동하는지 확인했는데 진짜 로봇 청소기를 돌리는 느낌이라 재밌었다 ㅎㅎ
'알고리즘' 카테고리의 다른 글
[프로그래머스] 기초 문제 풀이 (두 수의 합, 특정 문자열로 끝나는 가장 긴 부분 문자열 찾기, ad 제거하기, 접미사인지 확인하기, 공백으로 구분하기 1, X 사이의 개수) (0) | 2024.11.18 |
---|---|
[프로그래머스/Java] 코딩 기초 트레이닝 복습 (0) | 2024.09.12 |
[백준/Java] #16985 Maaaaaaaze (0) | 2023.06.20 |
[백준/Java] #18808 스티커 붙이기 (2) | 2023.06.02 |
[백준/Java] #4179 불! (⚠️시행착오 엄청 많음 주의⚠️) (1) | 2023.05.18 |