반응형
Approach
출처: https://www.acmicpc.net/problem/14503
#설계 #시뮬레이션
아래의 규칙을 기반으로 로봇 청소기가 청소하는 칸의 개수를 구하는 문제이다.
N*M 크기의 공간이 주어져 있고, 로봇은 (r, c)에 위치한다.
- 로봇청소기는 벽(1)이 아니면서 청소 가능한 칸이면 해당 칸으로 전지하여 청소한다.
- 청소할 수 없다면, 반시계방향(←↓→↑)으로 돌며 청소 가능한 칸을 확인한다.
(청소한 곳을 다시 청소하지는 않는다. 청소했던 지점으로 후진은 가능)
- 네 방향이 모두 벽이거나 청소가 되어 있다면 현재 바라보고 있는 방향을 유지한 채 후진한다.
- 후진도 할 수 없는 경우 작동을 멈춘다.
Case 1
처음 놓여진 곳을 청소한 후, 네 방향이 벽이므로 종료된다.
Case 2
주어진 [input]으로 로봇을 움직이면 아래와 같다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int M = Integer.parseInt(sc.next());
int N = Integer.parseInt(sc.next());
// robot 정보
int r = Integer.parseInt(sc.next());
int c = Integer.parseInt(sc.next());
int d = Integer.parseInt(sc.next());
Robot robot = new Robot(r, c, d);
int[][] map = new int[M][N];
for(int i=0; i<M; i++) {
for(int j=0; j<N; j++) {
map[i][j] = Integer.parseInt(sc.next());
}
}
// 로봇에 매뉴얼 세팅
robot.setMenual(new Menual());
// 로봇에 지도 세팅
robot.setMap(map);
// 로봇 동작
robot.run();
}
}
class Robot{
// 로봇 위치
int r, c;
// 방향(d): {0:북쪽(상), 1:동쪽(우), 2:남쪽(하), 3:서쪽(좌)}
int d;
int[][] map;
Menual menual;
public Robot(int r, int c, int d) {
this.r = r;
this.c = c;
this.d = d;
}
public void setMap(int[][] map) {
this.map = map;
}
public void setMenual(Menual menual) {
this.menual = menual;
}
/*
-1 : 청소한 칸
0 : 빈 칸
1 : 벽
*/
public void run() {
// 시작지점을 청소
map[r][c] = -1;
int result = 1;
while(true) {
// 만약 상하좌우 모두 벽이거나 청소한 곳이라면 후진(back)을 해야 한다.
boolean isBack = true;
// 현재 지점에서 바라보는 방향을 토대로 다음 탐색방향을 정하기
for(int i=0; i<4; i++) {
// 왼쪽 방향
if(menual.checkDireciton(d) == 3) {
// 모든 외곽은 벽으로 설정되어 있으니
// 현재 로봇의 위치를 기준으로 배열을 초과하는 경우는 없다.
d = 3; // 로봇의 방향을 바꾼다.
if(menual.checkClean(map[r][c-1])) {
isBack = false; // 후진할 필요가 없다.
c--; // 로봇을 이동시킨다.
break;
}
}
// 아래쪽 방향
else if(menual.checkDireciton(d) == 2) {
d = 2;
if(menual.checkClean(map[r+1][c])) {
isBack = false;
r++;
break;
}
}
// 오른쪽 방향
else if(menual.checkDireciton(d) == 1) {
d = 1;
if(menual.checkClean(map[r][c+1])) {
isBack = false;
c++;
break;
}
}
// 위쪽 방향
else if(menual.checkDireciton(d) == 0) {
d = 0;
if(menual.checkClean(map[r-1][c])) {
isBack = false;
r--;
break;
}
}
}
// 후진되는 경우라면 동서남북이 벽이거나 청소했다는 것.
if(isBack) {
// 이때 후진하는 곳이 벽인지 확인한다.
// 방향(d): {0:북쪽(위), 1:동쪽(오), 2:남쪽(아), 3:서쪽(왼)}
if(d == 3) {
// 방향이 위쪽이므로 아래쪽 칸을 확인한다.
if(map[r][c+1] == 1) {
// 벽이라면 더 이상 진행할 수 없으므로 결과값을 출력하고 종료
break;
}
// 후진을 할 수 있다는 것은 기존의 청소를 한 곳이다.
// 아래 후진
c++;
}else if(d == 2) {
if(map[r-1][c] == 1) {
break;
}
// 위로 후진
r--;
}else if(d == 1) {
if(map[r][c-1] == 1) {
break;
}
// 왼쪽 후진
c--;
}else if(d == 0) {
if(map[r+1][c] == 1) {
break;
}
// 오른쪽 후진
r++;
}
}
// 이동된 현재 지점을 청소한 영역(-1) 표시
if(isBack == false) {
map[r][c] = -1;
result++;
}
}
System.out.println(result);
}
}
class Menual{
// 청소 가능한 곳인지 확인
boolean checkClean(int target) {
// 벽이거나 이미 청소한 곳인 경우
if(target == 1 || target == -1) {
return false;
}
return true;
}
// 방향 바꾸기
int checkDireciton(int d) {
int direction;
if(d == 0) {
direction = 3;
}else if(d == 1) {
direction = 0;
}else if(d == 2) {
direction = 1;
}else{
direction = 2;
}
return direction;
}
}
반응형
'PS 문제 풀이 > Baekjoon' 카테고리의 다른 글
[BOJ] 백준 9669 애너그램 (Java) (0) | 2021.02.13 |
---|---|
[BOJ] 백준 15685 드래곤 커브 (0) | 2021.02.13 |
[BOJ] 백준 1676 팩토리얼 0의 개수 (Java) (0) | 2021.02.13 |
[BOJ] 백준 3040 백설 공주와 일곱 난쟁이(Java) (0) | 2021.02.13 |
[BOJ] 백준 1075 나누기 (Java) (0) | 2021.02.13 |
댓글