![[백준 14503] 로봇 청소기](https://image.inblog.dev?url=https%3A%2F%2Finblog.ai%2Fapi%2Fog%3Ftitle%3D%255B%25EB%25B0%25B1%25EC%25A4%2580%252014503%255D%2520%25EB%25A1%259C%25EB%25B4%2587%2520%25EC%25B2%25AD%25EC%2586%258C%25EA%25B8%25B0%26logoUrl%3Dhttps%253A%252F%252Finblog.ai%252Finblog_logo.png%26blogTitle%3DHossi%2520%257C%2520devlog&w=2048&q=75)
알고리즘 분류 - 구현 / 시뮬레이션
구현에서 가장 중요한 것은 “조건을 잘 지키는 것” 입니다. 조건을 잘 지키려면 “문제를 잘 읽어야” 합니다.
문제의 조건 분석
먼저 문제에서 제시한 조건들을 정리해봅시다.
- 현재 칸이 아직 청소되지 않은 경우, 1-1. 현재 칸을 청소한다.
- 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우, 2-1. 방향을 유지한 채, 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다. 2-2. 후진할 수 없다면 작동을 멈춘다.
- 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우, 3-1. 반시계 방향으로 90 회전한다. 3-2. 바라보는 방향 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다. 3-3. 1번으로 돌아간다.
입력 값은 다음과 같습니다.
(N, M)
: 방의 크기
(r, c)
: 처음 로봇의 좌표
d
: 방향 (0
: 북, 1
: 동, 2
: 남, 3
: 서)
room[][]
: 방의 상태 (0
: 청소되지 않은 방, 1
: 진입할 수 없는 벽)출력 값은 다음과 같습니다.
result
: 로봇청소기가 청소한 방의 개수조건을 토대로 로직 구성
문제 분석을 토대로 아래와 같이 로직을 구성할 수 있습니다.
1 | if (본인이 있는 방이 0 이면) {
2 | 청소한다.
3 | 청소한 방의 개수를 1개 추가한다.
4 | }
5 |
6 | do {
7 | 시계방향으로 90도 회전한다.
8 | if (0인 방을 바라보고 있으면) {
9 | 0인 방의 방향을 저장한다. // 초기값은 -1
10| }
11| } while (최대 4번까지)
12|
13| if (0인 방의 방향이 -1 이 아니면) {
14| 직진한다.
15| } else if (0인 방의 방향이 -1 이면) {
16| 그대로 후진한다.
17| if (로봇이 있는 방이 1 이면) {
18| 프로그램을 종료한다.
19| }
20| }
21|
22| Line 1 로 돌아가서 반복한다.
주의할 점은 “주변에 0인 방이 있다면, 이미 0인 방을 바라보고 있더라도 무조건 시계방향으로 90도 회전을 선행” 한다는 점입니다. 이는 Line 9 ~ 11 에 do while 문을 사용한 이유이기도 합니다.
구현에 있어서 한 가지 더 주의할 점이 있습니다.
”회전은 반시계방향이며, d의 값에 대한 방향 { 0:북, 1:동, 2:남, 3:서 }” 을 꼭 지켜야 한다는 것입니다.
final static int[] dx = {0, 1, 0, -1};
final static int[] dy = {-1, 0, 1, 0};
// 북쪽으로 이동하는 예제
// x + dx[0] -> x
// y + dy[0] -> y - 1
// 반시계 방향으로 회전 시 3 -> 2 -> 1 -> 0 인덱스 순서로 방문
로직을 정상적으로 수행하면 로봇은 아래와 같은 순서로 방을 방문합니다.

코드로의 구현
위에서 구성한 로직을 실제 코드로 변환하는 과정에서 참고할 사항은 아래와 같습니다.
- Line 6 ~ 11 → 별도의 메서드를 통해 구현
- Line 22 → 재귀(dfs) 를 통해 구현
- 편의를 위해 room[row][col] → room[y][x] 로 변경
import java.io.*;
import java.util.Arrays;
public class Main {
static int Y, X;
static int y, x;
static int initDir;
static int[][] room;
static int[][] cleaned;
static int count = 0;
// 0, 1, 2, 3 -> 북 동 남 서
final static int[] dx = {0, 1, 0, -1};
final static int[] dy = {-1, 0, 1, 0};
final static StringBuilder sb = new StringBuilder();
final static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
public static void input() throws IOException {
String[] NM = br.readLine().split(" ");
Y = Integer.parseInt(NM[0]);
X = Integer.parseInt(NM[1]);
room = new int[Y][X];
cleaned = new int[Y][X];
String[] rc = br.readLine().split(" ");
y = Integer.parseInt(rc[0]);
x = Integer.parseInt(rc[1]);
initDir = Integer.parseInt(rc[2]);
}
public static int getCleanableDir(int x, int y, int dir) {
for(int i = 0; i < 4; i++) {
dir--;
dir = (dir < 0) ? 3 : dir;
int newX = x+dx[dir];
int newY = y+dy[dir];
if(room[newY][newX] == 0 && cleaned[newY][newX] == 0) {
return dir;
}
}
return -1;
}
public static int dfs(int y, int x, int dir, int count) {
if(cleaned[y][x] == 0) {
cleaned[y][x] = 1;
count++;
}
int newDir = getCleanableDir(x, y, dir);
if(newDir != -1) {
int newX = x+dx[newDir];
int newY = y+dy[newDir];
count += dfs(newY, newX, newDir, 0);
} else {
int newX = x-dx[dir];
int newY = y-dy[dir];
if(room[newY][newX] == 0) {
count += dfs(newY, newX, dir, 0);
}
}
return count;
}
public static void solution() throws IOException {
String str = "";
int temp = 0;
while ((str = br.readLine()) != null) {
room[temp] = Arrays.stream(str.split(" ")).mapToInt(Integer::parseInt).toArray();
cleaned[temp] = Arrays.copyOf(room[temp], room[temp].length);
temp++;
}
count = dfs(y, x, initDir, 0);
sb.append(count);
}
public static void output() throws IOException {
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
bw.write(sb.toString());
bw.flush();
}
public static void main(String[] args) throws IOException {
input();
solution();
output();
}
}
Share article