문제
로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오.
로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북중 하나이다. 지도의 각 칸은 (r, c)로 나타낼 수 있고, r은 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로 부터 떨어진 칸의 개수이다.
로봇 청소기는 다음과 같이 작동한다.
- 현재 위치를 청소한다.
- 현재 위치에서 현재 방향을 기준으로 왼쪽 방향부터 차례대로 인접한 칸을 탐색한다.
- 왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번부터 진행한다.
- 왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
- 네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
- 네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.
로봇 청소기는 이미 청소되어있는 칸을 또 청소하지 않으며, 벽을 통과할 수 없다.
풀이
DFS 를 이용하면 된다.
처음 접근을 queue를 사용해서 queue 를 이용한 DFS로 구현하였다.
왼쪽으로 도는 방식은
for (int i = 1; i <= 4 ; i++) {
int ndir = now.dir - i;
if(ndir < 0) {
ndir += 4;
}
}
위 와 같이 - i 를 하고 그때 값이 음수면 4 를 더해주는 방식으로 구현하였다.
뒤를 보는 방식은
int ndir = (now.dir + 2) % 4;
2를 더해주고 mod4 를 하는 방식으로 구현하였다.
이제 문제에서 제시한 조건에 맞게만 구현하면 된다
<전체코드>
package sw_solution;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;
public class Main {
static int N, M;
static int[][] map;
static int[][] direction = { { -1, 0 }, { 0, 1 }, { 1, 0 }, { 0, -1 } };
static boolean[][] visited;
static int answer;
public static int parseInt(String string) {
return Integer.parseInt(string);
}
public static void main(String[] args) throws IOException {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(bufferedReader.readLine());
N = parseInt(st.nextToken());
M = parseInt(st.nextToken());
st = new StringTokenizer(bufferedReader.readLine());
int x = parseInt(st.nextToken());
int y = parseInt(st.nextToken());
int dir = parseInt(st.nextToken());
map = new int[N][M];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(bufferedReader.readLine());
for (int j = 0; j < M; j++) {
map[i][j] = parseInt(st.nextToken());
}
}
visited = new boolean[N][M];
answer = 0;
System.out.println(start(x, y, dir));
}
static int start(int r, int c, int dir) {
int sum = 1;
visited[r][c] = true;
Queue<point> queue = new LinkedList<>();
queue.add(new point(r, c, dir));
cleaning: while (!queue.isEmpty()) {
point now = queue.poll();
// 청소 가능 한 곳 찾은 경우
for (int i = 1; i <= 4 ; i++) {
int ndir = now.dir - i;
if(ndir < 0) {
ndir += 4;
}
int nx = now.x + direction[ndir][0];
int ny = now.y + direction[ndir][1];
if(nx < 0 || nx >= N || ny < 0 || ny >= M || map[nx][ny] != 0) { continue;}
if(visited[nx][ny]) {continue;}
sum++;
visited[nx][ny] = true;
queue.add(new point(nx, ny, ndir));
continue cleaning;
}
int ndir = (now.dir + 2) % 4;
int nx = now.x + direction[ndir][0];
int ny = now.y + direction[ndir][1];
if (nx < 0 || nx >= N || ny < 0 || ny >= M || map[nx][ny] == 1) {
break;
}
queue.add(new point(nx, ny, now.dir));
}
return sum;
}
static class point {
int x, y, dir;
point(int x, int y, int dir) {
this.x = x;
this.y = y;
this.dir = dir;
}
}
}
'알고리즘 공부 > 구현 , 시뮬레이션' 카테고리의 다른 글
[백준] 17140 이차원 배열과 연산 (0) | 2021.10.20 |
---|---|
[백준] 20061 모노미도미노 2 (0) | 2021.10.20 |
[백준] 14499 주사위 굴리기 (0) | 2021.10.20 |
[백준] 16234 인구 이동 (0) | 2021.10.19 |
[백준] 19238 스타트 택시 (0) | 2021.10.19 |