반응형
문제

문제접근 방법
해당문제는 N과 M크기의 방이 존재하고 아래와 같이 동작할 때 로봇청소기가 작동을 시작한 후 작동을 멈출 때까지 청소하는 칸의 개수를 출력하는 프로그램을 작성하는 문제이다. 작동 방식은 다음과 같다.
- 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
- 현재 칸의 주변 칸 중 청소되지 않은 빈 칸이 없는 경우,
- 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
- 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
- 현재 칸의 주변 칸 중 청소되지 않은 빈 칸이 있는 경우,
- 반시계 방향으로 회전한다.
- 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈칸인 경우 한 칸 전진한다.
- 1번으로 돌아간다.
문제를 보고 구현문제라는 것을 파악 후 조건을 계속해서 읽으면서 이해했다. 그 결과 총 4가지의 핵심 기능으로 나누어
접근하기로 결정하였고 코드는 아래와 같다.
< 최종 코드 >
import java.util.*;
public class Main {
public static boolean visited[][];
public static int map[][];
public static int cnt = 0;
public static void main(String args[]) {
Scanner s = new Scanner(System.in);
int n = s.nextInt();
int m = s.nextInt();
visited = new boolean[n][m];
map = new int[n][m];
int y = s.nextInt();
int x = s.nextInt();
int d = s.nextInt();
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
map[i][j] = s.nextInt();
}
}
dfs(y, x, d, 0);
System.out.print(cnt);
}
public static void dfs(int y, int x, int d, int nsew) {
if (map[y][x] == 1) return;
if (!visited[y][x]) {
visited[y][x] = true;
map[y][x] = 2;
cnt++;
}
int[] dx = {0, 1, 0, -1};
int[] dy = {-1, 0, 1, 0};
if (nsew == 4) {
int backY = y;
int backX = x;
switch (d) {
case 0: backY += 1; break;
case 1: backX -= 1; break;
case 2: backY -= 1; break;
case 3: backX += 1; break;
}
if (backX < 0 || backY < 0 || backX >= map[0].length || backY >= map.length || map[backY][backX] == 1) return;
y = backY;
x = backX;
nsew = 0;
}
int count = 0;
while (count != 4) {
d = (d + 3) % 4;
int nx = x + dx[d];
int ny = y + dy[d];
if (nx >= 0 && ny >= 0 && nx < map[0].length && ny < map.length) {
if (map[ny][nx] == 0 && !visited[ny][nx]) {
dfs(ny, nx, d, 0);
return;
}
}
count++;
nsew++;
}
dfs(y, x, d, nsew);
}
}
최종 코드에서는 핵심로직 4가지만 소개하고 간단하게 넘어가도록 하겠다. 4가지는 아래와 같다.
- 현재 위치 청소하기
- 왼쪽 방향부터 회전하며 탐색
- 네 방향 다 안 되면 후진 (불가능하면 종료)
- DFS 재귀 호출로 반복
본인이 생각한 핵심로직은 이렇게 4가지이고 이렇게 코드를 작성하였다.
1. 현재 칸 청소하기
if (!visited [y][x]) { visited[y][x] = true; map [y][x] = 2; cnt++; }
- 로봇이 도착한 칸이 아직 청소되지 않았다면, 청소 처리 후 방문 체크(visited=true).
- 청소된 칸 수를 cnt에 누적.
- 문제 설명의 1번 규칙(현재 칸 청소) 구현 부분이다.
2. 왼쪽 방향 탐색 및 회전 처리
d = (d + 3) % 4; // 반시계 방향 회전
int nx = x + dx [d];
int ny = y + dy [d];...
if (map [ny][nx] == 0 &&! visited [ny][nx]) {
dfs(ny, nx, d, 0);
return; }
- 현재 방향 기준으로 왼쪽으로 회전한 뒤 앞칸을 확인.
- 앞칸이 빈칸(0)이고 아직 청소하지 않은 칸이면 그쪽으로 이동.
- 이동 시 DFS 재귀 호출로 다시 청소 시작.
- 문제 설명의 2번 규칙(왼쪽부터 차례로 탐색, 청소할 수 있으면 이동) 부분이다.
3. 네 방향 다 불가능할 때
if (nsew == 4) {
int backY = y, backX = x;
switch (d) {
case 0: backY += 1; break;
case 1: backX -= 1; break;
case 2: backY -= 1; break;
case 3: backX += 1; break; }
if (backX < 0 || backY < 0 || backX >= map [0]. length || backY >= map.length || map [backY][backX] == 1) return;
y = backY;
x = backX;
nsew = 0; }
- 네 방향 모두 청소할 수 없는 경우(nsew==4), 현재 방향은 유지한 채 뒤쪽 칸으로 후진.
- 뒤쪽이 벽이면 그대로 종료.
- 문제 설명의 3번 규칙(네 방향 모두 청소 불가 → 후진, 후진 불가 시 종료) 부분이다.
4. DFS 재귀 반복
dfs(ny, nx, d, 0); // 이동 가능한 경우
dfs(y, x, d, nsew); // 이동 불가능 → 회전 횟수 늘리고 반복
- 이동 가능하면 새로운 위치로 재귀 진입, 청소 이어가기.
- 이동 불가능하면 같은 자리에서 방향 회전만 하면서 다시 반복.
- 후진이나 종료 조건에 도달할 때까지 계속 재귀 호출이 이어진다
마무리
구현 문제들은 항상 아이디어는 쉽게 떠오르지만 그 과정이어렵운것 같다. 조금 더 문제를 분석하고 파악하는 능력을 키울 필요를 느끼었다.
'문제풀이 > 구현' 카테고리의 다른 글
| [문제 풀이] 백준 17144번 미세먼지 안녕! JAVA (0) | 2025.08.03 |
|---|---|
| [문제 풀이] 백준 3190번 뱀 JAVA (0) | 2025.07.27 |
| [문제 풀이] 백준 20055번 컨베이어 벨트 위의 로봇 JAVA (0) | 2025.07.20 |
| [문제 풀이] 백준 14890번 경사로 JAVA (0) | 2025.07.18 |
| [문제 풀이] 백준 14891번 톱니바퀴 JAVA (0) | 2025.07.04 |