Gold V
https://www.acmicpc.net/problem/14503
14503번: 로봇 청소기
로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어
www.acmicpc.net
로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오.
로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북중 하나이다. 지도의 각 칸은 (r, c)로 나타낼 수 있고, r은 북쪽으로부터 떨어진 칸의 개수, c는 서쪽으로 부터 떨어진 칸의 개수이다.
로봇 청소기는 다음과 같이 작동한다.
- 현재 위치를 청소한다.
- 현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
- 왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번부터 진행한다.
- 왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
- 네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
- 네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.
로봇 청소기는 이미 청소되어있는 칸을 또 청소하지 않으며, 벽을 통과할 수 없다.
input:
- 첫째 줄에 세로 크기 N과 가로 크기 M이 주어진다. (3 ≤ N, M ≤ 50)
- 둘째 줄에 로봇 청소기가 있는 칸의 좌표 (r, c)와 바라보는 방향 d가 주어진다. d가 0인 경우에는 북쪽을, 1인 경우에는 동쪽을, 2인 경우에는 남쪽을, 3인 경우에는 서쪽을 바라보고 있는 것이다.
- 셋째 줄부터 N개의 줄에 장소의 상태가 북쪽부터 남쪽 순서대로, 각 줄은 서쪽부터 동쪽 순서대로 주어진다. 빈 칸은 0, 벽은 1로 주어진다. 지도의 첫 행, 마지막 행, 첫 열, 마지막 열에 있는 모든 칸은 벽이다.
- 로봇 청소기가 있는 칸의 상태는 항상 빈 칸이다.
output:
- 로봇 청소기가 청소하는 칸의 개수를 출력한다.
Idea :
- 단순 구현 문제
- 현재 위치, 방향 기준 왼쪽 방향부터 시작하여 반시계방향으로 돌면서 청소 가능한 곳(청소X, 벽X) 찾기
- 청소가능한 곳을 찾았으면 그 방향으로 회전 후 위 동작을 다시 반복
- 청소가능한 곳이 없으면 처음 방향 기준으로 청소 가능한 곳이 나올 때까지 후진
- 후진해서 청소가능한 곳을 찾았으면 첫번째 동작부터 다시 반복
- 벽이 나왔을 경우 더 이상 청소 할 수 없음, 결과를 출력하고 프로그램 종료
Code :
#include <iostream>
using namespace std;
struct Point {
int r, c;
Point(int _r, int _c) : r(_r), c(_c) {}
};
#define NOTHING 0
#define WALL 1
#define CLEANED 2
int N, M;
int map[50][50] = {};
int RR[4] = {-1, 0, 1, 0};
int CC[4] = {0, 1, 0, -1};
int ans = 0;
/* solve: 재귀를 이용해 로봇청소기가 청소한 칸 수를 구하는 함수
*
* parameters - cur: 로봇청소기의 현재 위치/좌표
* d: 로봇청소기가 바라보고 있는 현재 방향
* return: none
*/
void solve(Point cur, int d) {
if (!map[cur.r][cur.c]) ans++;
map[cur.r][cur.c] = CLEANED;
int next_r, next_c, next_d;
// 현재 위치의 왼쪽 방향부터 시작해서 반시계방향으로 돌면서 청소 가능한 곳 찾기
for (int i=3; i>=0; i--) {
next_d = (i + d) % 4;
next_r = cur.r + RR[next_d];
next_c = cur.c + CC[next_d];
if (map[next_r][next_c] != NOTHING) continue;
solve(Point(next_r, next_c), next_d);
return;
}
// 현재 위치의 주변에 청소 가능한 곳이 없을 경우
// 청소 가능한 곳이 나올 때까지 후진 (처음 방향 기준)
next_r = cur.r;
next_c = cur.c;
while (true) {
next_r -= RR[d];
next_c -= CC[d];
// 벽이 나오면 더 이상 청소 가능한 곳이 없음을 의미
if (map[next_r][next_c] == WALL) return;
solve(Point(next_r, next_c), d);
return;
}
}
int main() {
ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL);
// freopen("input.txt", "rt", stdin);
int r, c, d;
/* input */
cin >> N >> M;
cin >> r >> c >> d;
for (int i=0; i<N; i++) {
for (int j=0; j<M; j++) {
cin >> map[i][j];
}
}
/* solve */
solve(Point(r, c), d);
/* print answer */
cout << ans << "\n";
}
Result :
메모리: 2032 KB, 시간: 0 ms
Review :
'코딩테스트 연습' 카테고리의 다른 글
[BOJ] 17829. 222-폴링 (divide_and_conquer, implementation, recursion) (0) | 2022.12.29 |
---|---|
[BOJ] 1707. 이분그래프 (bipartite_graph, dfs, bfs) (0) | 2022.12.27 |
[BOJ] 1182. 부분수열의 합 (backtracking, bruteforcing) (0) | 2022.12.26 |
[BOJ] 1188. 음식 평론가 (euclidean, math, number_theory) (0) | 2022.12.21 |
[BOJ] 2583. 영역 구하기 (bfs, dfs, graphs, graph_traversal) (0) | 2022.12.21 |