Algorithm/BaekJoon
[14503 로봇청소기]
돌건
2021. 3. 17. 21:00
14503번: 로봇 청소기
로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어
www.acmicpc.net
- 분석
단순 시뮬레이션 문제이다. 크게 1단계, 2단계가 존재한다. 이에 따라 1단계, 2단계에서 해야하는 일들을 함수로 정의해주었다. 1단계 - solution, 2단계 - stepTwo 로 정의하였다. 각 과정에 해당하는 부분을 주석으로 적어두었기 때문에 자세한 해설을 넘어가도록 하겠다.
#include <iostream>
#include <vector>
using namespace std;
int N, M, direction, answer;
int dy[4] = {-1, 0, 1, 0};
int dx[4] = {0, 1, 0, -1};
pair<int, int> robot;
vector<vector<int> > board;
vector<vector<bool> > visited;
void solution(int y, int x, int d, int originDir);
void stepTwo(int y, int x, int d, int originDir);
bool isInBoard(int y, int x);
int main()
{
ios_base ::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N >> M;
board.assign(N, vector<int>(M, 0));
visited.assign(N, vector<bool>(M, false));
cin >> robot.first >> robot.second >> direction;
for(int row = 0; row < N; row++) {
for(int col = 0; col < M; col++) {
cin >> board[row][col];
}
}
solution(robot.first, robot.second, direction, direction);
cout << answer << endl;
return 0;
}
void solution(int y, int x, int d, int originDir) {
// 1. 현재 위치를 청소한다.
visited[y][x] = true;
answer++;
// 2. 현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 탐색을 진행한다.
stepTwo(y, x, d, originDir);
}
void stepTwo(int y, int x, int d, int originDir) {
// 왼쪽 방향
int leftDir = (d + 3) % 4;
// 왼쪽 방향으로 한칸 간 위치
int ny = y + dy[leftDir];
int nx = x + dx[leftDir];
// a. 왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번부터 진행한다.
if(isInBoard(ny, nx) && board[ny][nx] == 0 && !visited[ny][nx]) {
solution(ny, nx, leftDir, leftDir);
}
else if(!isInBoard(ny, nx) || board[ny][nx] == 1 || visited[ny][nx]) {
if(leftDir == originDir) {
// c. 네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
int backDir = (originDir + 2) % 4;
int backY = y + dy[backDir];
int backX = x + dx[backDir];
if(isInBoard(backY, backX) && board[backY][backX] == 0) {
stepTwo(backY, backX, originDir, originDir);
}
// d. 네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.
else {
return;
}
}
else {
// b. 왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
stepTwo(y, x, leftDir, originDir);
}
}
}
bool isInBoard(int y, int x) {
return (y >= 0 && y < N && x >= 0 && x < M);
}