문제
로봇 청소기가 있는 장소 N x M 은 빈칸(0) 또는 벽(1)으로 이뤄져있다. 일정한 규칙을 가지고 움직이는 로봇청소기를 이용할 때 청소한 영역의 개수를 구하는 문제이다.로봇청소기의 작동 규칙은 아래와 같다.
현재 위치를 청소한다.
현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
1) 왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번 부터 진행한다. 2) 왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다. 3) 네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다. 4) 네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.
접근방법
- 조건을 그래도 코드로 옮기면 된다. - 청소기의 방향인 북(0), 동(1), 남(2), 서(3) 에서 왼쪽을 보게되면 서(3), 북(0), 동(1), 남(2)을 바라보게 되는데, 이는 switch-case 구문보다 각 방향값에서 1을 빼주는 방법을 사용해 더 깔끔하게 코드를 짤 수 있다.(효근짱b) - 청소기가 네 방향을 모두 탐색한 것은 stay_time 이라는 변수를 두어 해결하였다.
import java.util.Scanner;
public class Main{
static int N;
static int M;
static int map[][];
static int cur_dir;
static class Pos{ int r; int c; }
public static int changDir(int dir){
return (dir == 0)? 3 : dir-1;
}
public static Pos changePos(int dir, Pos pos){
Pos next_pos = new Pos();
next_pos.r = pos.r;
next_pos.c = pos.c;
switch (dir){
case 0: --next_pos.r; break; // 북
case 1: ++next_pos.c; break; // 동
case 2: ++next_pos.r; break; // 남
case 3: --next_pos.c; break; // 서
}
return next_pos;
}
public static Pos backPos(int dir, Pos pos){
Pos next_pos = new Pos();
next_pos.r = pos.r;
next_pos.c = pos.c;
switch (dir){
case 0: ++next_pos.r; break; // 북
case 1: --next_pos.c; break; // 동
case 2: --next_pos.r; break; // 남
case 3: ++next_pos.c; break; // 서
}
return next_pos;
}
public static int cleaning(int map[][], int N, int M, Pos start){
int result = 0;
Pos cur_pos = new Pos();
Pos before_pos = new Pos();
cur_pos.c = before_pos.c = start.c;
cur_pos.r = before_pos.r = start.r;
int stay_time = 0;
while(true){
// 1. 현재 위치를 청소한다.
if(map[cur_pos.r][cur_pos.c] == 0){
map[cur_pos.r][cur_pos.c] = 2;
++result;
//printarr(map);
}
// 2. 현재 위치에서 현재방향을 기준으로 왼쪽부터 탐색을 진행한다.
cur_dir = changDir(cur_dir);
Pos search_pos = changePos(cur_dir, cur_pos);
++stay_time;
// 2-1. 왼쪽방향에 아직 청소하지 않은 공간이 있다면 청소
if(map[search_pos.r][search_pos.c] == 0){
cur_pos.r = search_pos.r; // 현재 위치 변경
cur_pos.c = search_pos.c;
stay_time = 0; // stay time 초기화
}
if(stay_time == 4){
search_pos = backPos(cur_dir, cur_pos);
// 뒤쪽이 벽이면
if(map[search_pos.r][search_pos.c] == 1){
break;
}else{
// 2-3. 후진
cur_pos.r = search_pos.r;
cur_pos.c = search_pos.c;
stay_time = 0;
}
}
}
return result;
}
private static void printarr(int arr[][]){
System.out.println();
for(int i=1; i<arr.length-1; i++){
for(int j=1; j<arr[0].length-1; j++)
System.out.print(map[i][j] + " ");
System.out.println();
}
}
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
M = sc.nextInt();
map = new int[N+2][M+2];
for(int i=0; i<N+2; i++)
for(int j=0; j<M+2; j++)
map[i][j] = 1;
Pos start = new Pos();
start.r = sc.nextInt() + 1;
start.c = sc.nextInt() + 1;
cur_dir = sc.nextInt();
for(int i=1; i<=N; i++)
for(int j=1; j<=M; j++)
map[i][j] = sc.nextInt();
int result = cleaning(map, N, M, start);
System.out.println(result);
}
}
'알고리즘' 카테고리의 다른 글
백준15684 : 사다리 조작 (0) | 2018.11.21 |
---|---|
백준14889 : 스타트와 링크 (0) | 2018.11.16 |
[JAVA] 백준 3055 : 탈출 (0) | 2018.09.27 |
[JAVA] 백준 11559 : 뿌요뿌요 (0) | 2018.09.20 |
[JAVA] 백준 3190 : 뱀 (1) | 2018.09.18 |