문제 링크 ▶︎ 로봇 청소기

문제에는 이러한 조건에 따라서 로봇 청소기가 움직이는데 크게 보면 현재 칸의 주변 4칸 중 청소되지 않은 빈칸이 있느냐 없느냐로 두 갈래로 나뉘고 그 다음은 각각의 오더가 있기 때문에 항상 현재 칸에서 주변 4칸 검사를 하는 것이 선행되어야 한다. 이후에 조건은 if문을 통해서 모두 처리해주면 될 것이다.
그리고 변수 d를 통해서 로봇 청소기가 바라보는 방향이 존재하기 때문에 0,1,2,3에 맞춰서 로직을 구성하면 된다.
앞서 말한대로 주변 4칸 검사에 대한 메서드가 필요한데 wall 이라는 함수를 통해서 동서남북을 모두 검사하면서 범위안에 들어가고 방문하지 않았으며 벽이 아닌 곳이 있는지 없는지를 true, false로 리턴하는 함수를 만든다.
이후에 무한 반복 while문을 돌면서 현재 칸에 처음 방문하면 방문 처리와 동시에 answer++ 을 해준다. 이 작업의 이유는 다시 방문하는 작업도 수행되기 때문에 첫 방문을 체크해주는 것이다.
그 다음에는 현재 칸에서 주변 4칸 검사를 진행하는데 그 결과에 따라 만약 주변 4칸에 갈 곳이 있으면 그 반시계 방향 90도 회전하는 작업을 하는데, 그 로직으로는 d가 0,1,2,3 로 표현되기 때문에 나머지를 4로 나눈 나머지를 활용해 반시계 방향으로 90도 돈 것을 처리해준다.
그리고 전진할 수 있을 때까지 반시계로 90도 돌다가 전진해준다.
만약 주변 4칸에 갈 곳이 없으면 역방향으로 가주는데 이것은 r - dirs[d][0] 이런 식으로 빼기 연산을 통해 구현해주고 벽을 만나면 바로 조건문을 탈출해준다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
public class Main {
public static int n, m;
public static int[][] dirs = new int[][]{{-1,0}, {0,1}, {1,0}, {0,-1}};
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());
int[][] grid = new int[n][m];
st = new StringTokenizer(br.readLine());
int r = Integer.parseInt(st.nextToken());
int c = Integer.parseInt(st.nextToken());
int d = Integer.parseInt(st.nextToken());
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < m; j++) {
grid[i][j] = Integer.parseInt(st.nextToken());
}
}
int answer = 0;
boolean[][] visited = new boolean[n][m];
while (true) {
if (!visited[r][c] && grid[r][c] == 0) {
visited[r][c] = true;
answer++;
}
if (wall(r, c, grid, visited)) {
d = (d + 3) % 4;
while (visited[r + dirs[d][0]][c + dirs[d][1]] || grid[r + dirs[d][0]][c + dirs[d][1]] == 1) {
d = (d + 3) % 4;
}
r += dirs[d][0];
c += dirs[d][1];
} else {
int nr = r - dirs[d][0];
int nc = c - dirs[d][1];
if (grid[nr][nc] == 1) {
break;
} else {
r = nr;
c = nc;
}
}
}
System.out.println(answer);
}
public static boolean wall (int r, int c, int[][] grid, boolean[][] visited) {
for (int[] dir : dirs) {
int nr = r + dir[0];
int nc = c + dir[1];
if (0 <= nr && nr < n && 0 <= nc && nc < m) {
if (grid[nr][nc] == 0 && !visited[nr][nc]) {
return true;
}
}
}
return false;
}
}
문제에 대한 이해가 어려웠다. 각각의 조건을 어떤 식으로 처리할 지 고민하는 데 시간을 많이 썼고 실제 구현은 여러 방법으로 할 수 있을 것 같다.