March 13, 2021
https://www.acmicpc.net/problem/14503
문제
로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오.
로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북중 하나이다. 지도의 각 칸은 (r, c)로 나타낼 수 있고, r은 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로 부터 떨어진 칸의 개수이다.
로봇 청소기는 다음과 같이 작동한다.
현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
로봇 청소기는 이미 청소되어있는 칸을 또 청소하지 않으며, 벽을 통과할 수 없다.
입력
첫째 줄에 세로 크기 N과 가로 크기 M이 주어진다. (3 ≤ N, M ≤ 50)
둘째 줄에 로봇 청소기가 있는 칸의 좌표 (r, c)와 바라보는 방향 d가 주어진다. d가 0인 경우에는 북쪽을, 1인 경우에는 동쪽을, 2인 경우에는 남쪽을, 3인 경우에는 서쪽을 바라보고 있는 것이다.
셋째 줄부터 N개의 줄에 장소의 상태가 북쪽부터 남쪽 순서대로, 각 줄은 서쪽부터 동쪽 순서대로 주어진다. 빈 칸은 0, 벽은 1로 주어진다. 지도의 첫 행, 마지막 행, 첫 열, 마지막 열에 있는 모든 칸은 벽이다.
로봇 청소기가 있는 칸의 상태는 항상 빈 칸이다.
출력
로봇 청소기가 청소하는 칸의 개수를 출력한다.
처음에는 문제에서 요구하는대로 그대로 구현해보려고 했는데, 테스트케이스는 통과하지만 틀렸습니다를 계속 받았다. 하루종일 이리저리 고쳐보다가 포기하고 dfs로 방향을 틀어서 다시 구현하기 시작했다. dfs는 어떻게 할지 대충 감은 오지만 계속 변경되는 방향을 처리하는 로직을 짜는데 어려움을 많이 겪었고 하루종일 붙잡고 씨름하다가 결국에는 블로그글들을 보고 풀게되었다.
일반적인 dfs 를 사용하지만 방향을 설정할때 아무방향이나 순서대로 넣으면 안된다. 따라서 일단 방향을 왼쪽으로 한번 돌려놓고(i = dir - 1) 방향을 왼쪽으로 돌리면서(i--) 네 번 반복하도록 한다. 그리고 다음 dfs 재귀호출에 사용할 방향은 ( i + 4 ) % 4 로 얻어낸다. 이렇게 하면 특정한 방향에서부터 왼쪽방향으로 방향을 변경ㄹ하면서 재귀호출을 할 수 있다. 해당 방향에 0이 있다면 곧바로 청소를 해야하기 때문에 0이 아닌 숫자로 채우고 (나는 디버깅할때 방문 순서를 쉽게 파악하기 위해서 정수를 계속 증가시키며 넣었다.), 만약 더 이상 청소할 곳이 없다면, 현재 방향은 그대로 유지한 채로 뒷방향으로 이동하는 재귀호출을 수행한다.
나는 벽과의 구분을 위해 청소된 구역을 의미하는 값을 2부터 시작했기 때문에, 최종적으로 값을 출력할 때는 최종 이동횟수 - 1 을 출력해주었다.
' '
#include <cstdio>
#include <utility>
using namespace std;
int N, M;
int map [51][51];
int steps = 1;
bool isInMap(int row, int col){
return row >= 1 && row <= N && col >= 1 && col <= M;
}
void dfs(int row, int col, int dir){
int rowDir [] = {-1, 0, 1, 0};
int colDir [] = {0, 1, 0, -1};
int rowRearDir [] = {1, 0, -1, 0};
int colRearDir [] = {0, -1, 0, 1};
if (map[row][col] == 0){
steps += 1;
map[row][col] = steps;
}
for (int i = dir-1 ; i > dir-5 ; i--){
int nextDir = (i + 4) % 4;
int nextRow = row + rowDir[nextDir];
int nextCol = col + colDir[nextDir];
if (isInMap(nextRow, nextCol) && map[nextRow][nextCol] == 0){
dfs(nextRow, nextCol, nextDir);
return;
}
}
int nextRearRow = row + rowRearDir[dir];
int nextRearCol = col + colRearDir[dir];
if (!(map[nextRearRow][nextRearCol] == 1)){
dfs(nextRearRow, nextRearCol, dir);
}
}
int main (){
scanf("%d %d",&N, &M);
int r, c, dir;
scanf("%d %d %d", &r, &c, &dir);
for (int i = 0 ; i < N ; i++){
for (int j = 0 ; j < M ; j++){
scanf("%d", &map[i][j]);
}
}
dfs(r, c, dir);
printf("%d", steps-1);
}