[BOJ 14503] 로봇청소기
업데이트:
문제
- BOJ 14503
- 문제의 저작권은 Baekjoon Online Judge에 있습니다.
접근방식
이 문제는 재귀로 해결했으며, 호출한 시점으로 다시 돌아오지 않으므로 함수 호출 후 다음 라인에 return
을 꼭 해줘야한다.
해결해야 하는 순서대로 코드를 짜면 되므로 크게 어렵지 않은 문제다.
주의할점으로는 무조건 반시계방향으로 탐색하면 되는 줄 알았는데, 바뀐 방향을 기준으로 두고 다음 왼쪽방향이 무엇인지 조건을 걸어주어야 한다.
그래서, 쉽게 생각하기 위해 if문으로 하나씩 조건을 걸어서 현재 방향에 대한 왼쪽 방향을 구해줬다.(후진도 마찬가지)
다른 코드를 보니 (d+3)%4
로 다음 왼쪽에 해당하는 방향을 간결하게 구해줄 수 있었다.
1. 재귀
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
//로봇청소기
public class Main {
static int N, M; //세로, 가로
static int[] di = {-1, 0, 1, 0}; //북동남서
static int[] dj = {0, 1, 0, -1};
static int Ans; //청소영역개수
static int[][] map;
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());
map = 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++) {
map[i][j]= Integer.parseInt(st.nextToken());
}
}//input
map[r][c] = -1;
recur(r, c, d);
for(int i=0; i<N; i++) {
for(int j=0; j<M; j++) {
if(map[i][j] == -1) Ans++;
}
}
System.out.println(Ans);
}
static void recur(int r, int c, int d) {
int nd = 0; //다음 방향
//2. 현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
for(int i=0; i<4; i++) {
if(d == 0) nd=3;
else if(d==1) nd=0;
else if(d==2) nd=1;
else nd=2;
int nr = r + di[nd];
int nc = c + dj[nd];
//왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 처음 부터 진행한다.
if(nr>=0 && nr<N && nc>=0 && nc<M && map[nr][nc]!=-1 && map[nr][nc] != 1) {
map[nr][nc] = -1; //1. 현재 위치 청소
recur(nr, nc, nd);
return;
}else{//왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
d = nd;
}
}
//네 방향 모두 청소가 이미 되어있거나 벽인 경우에는,
//바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
int bd = 0; //후진방향
if(d==0) bd=2;
else if(d==1) bd=3;
else if(d==2) bd=0;
else bd=1;
int nr = r + di[bd];
int nc = c + dj[bd];
if(nr>=0 && nr<N && nc>=0 && nc<M && map[nr][nc] != 1) {
recur(nr, nc, d);
return;
}else return; // 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.
}
}
2. while문
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main {
static int N, M; // height, width
static int[][] map;
static int d;
static int nowX, nowY;
static int[] di = { -1, 0, 1, 0 }; // north, east, south, west
static int[] dj = { 0, 1, 0, -1 };
static int Ans = 0;
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());
map = new int[N][M];
st = new StringTokenizer(br.readLine());
nowX = Integer.parseInt(st.nextToken());
nowY = Integer.parseInt(st.nextToken());
d = Integer.parseInt(st.nextToken());
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < M; j++)
map[i][j] = Integer.parseInt(st.nextToken());
} // End input
// 1:wall, -2:cleaned
while (true) {
// showMap();
// 1. clean current position
if (map[nowX][nowY] == 0) {
map[nowX][nowY] = -2;
Ans++;
}
// 2. 4 direction search
int nx = 0, ny = 0, nd = 0;
boolean endSearch = false;
for (int i = 0; i < 4; i++) {
nd = (d + 3) % 4; // next direction
nx = nowX + di[nd];
ny = nowY + dj[nd];
// a
if (nx >= 0 && nx < N && ny >= 0 && ny < M && map[nx][ny] != -2 && map[nx][ny] != 1) {
nowX = nx;
nowY = ny;
d = nd;
break;
} else d = nd;
if(i == 3) endSearch = true;
}//End 4search
int rd = 0;
//c
if (endSearch) {
// go rear
if(d==0) rd=2;
else if(d==1) rd=3;
else if(d==2) rd=0;
else rd=1;
int rx = nowX + di[rd];
int ry = nowY + dj[rd];
if (rx >= 0 && rx < N && ry >= 0 && ry < M && map[rx][ry] != 1) {
nowX = rx;
nowY = ry;
} else break;
}
} // End clean
System.out.println(Ans);
}
}