Baekjoon/Gold

C++ / 백준 / 14503 / 로봇 청소기

GitHubSeob 2021. 8. 13. 02:21

문제

https://www.acmicpc.net/problem/14503

 

14503번: 로봇 청소기

로봇 청소기가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오. 로봇 청소기가 있는 장소는 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1크기의 정사각형 칸으로 나누어

www.acmicpc.net

 

문제풀이

현재 위치에서 바라보는 방향 기준 왼쪽부터 반시계 방향으로 돌면서 청소할 칸을 확인한다.

청소할 칸이 있으면 청소할 칸 쪽으로 회전을 한 뒤 한 칸 이동한다.

벽이거나 청소할 칸이 없으면 다시 회전을 한다.

네 방향을 탐색했으면 90도의 회전이 총 네 번 있었으므로 방향이 처음 방에 들어온 상태로 된다.

뒷 칸이 벽이면 작동을 멈춘다. 뒷 칸이 벽이 아니면 뒤로 한 칸 이동한다.

 

vector<int>robot(3,0);
vector<vector<int>>Arr;
vector<pair<int, int>>loc = { { 0,-1 }, {1, 0}, {0, 1}, {-1, 0}  };
	cin >> robot[0] >> robot[1] >> robot[2];
	robot[2] = (4 - robot[2]) % 4;

robot벡터는 현재 로봇의 상태를 나타낸다. { y좌표, x좌표, 바라보는 방향}이다.

Arr은 칸의 상태들을 나타내는 2차원 벡터.

바라보는 방향 기준 왼쪽 칸을 탐색하므로

loc벡터는 현재 칸 기준 서쪽, 남쪽, 동쪽, 북쪽 방향 순으로 (반시계 방향) 나열했다.

문제에서는 0: 북쪽, 1: 동쪽을, 2: 남쪽, 3: 서쪽 이기 때문에 좀 헷갈릴 수도 있다.

처음 입력받을 때 한 번만 (4 - 입력값)%4를 하여 문제에 나온 대로 설정해준다.

 

void Clean() {
	if (Arr[robot[0]][robot[1]] == 0) clean_cnt++;
	Arr[robot[0]][robot[1]] = 2;

	while (1) {
		int dir = robot[2];
		int cnt = 0;
		for (cnt = 0; cnt < 4; ++cnt) {
			dir = robot[2];
			int n_y = robot[0] + loc[dir].first;
			int n_x = robot[1] + loc[dir].second;
			if (n_y >= 0 && n_y < N && n_x >= 0 && n_x < M) {
				if (Arr[n_y][n_x] == 0) {
					Arr[n_y][n_x] = 2;
					robot[0] = n_y;
					robot[1] = n_x;
					robot[2] = (dir + 1) % 4;
					clean_cnt++;
					break;
				}
				else {
					robot[2] = (dir + 1) % 4;
				}
			}
		}
		if (cnt == 4) {
			robot[0] += loc[(dir + 2) % 4].first;
			robot[1] += loc[(dir + 2) % 4].second;
			if (Arr[robot[0]][robot[1]] == 1)
				return;
		}
	}
}

총 네 방향을 봐야 탐색해 야하므로 탐색하는 새로운 y, x좌표들을 현재 로봇 위치 + loc벡터를 이용하여 네 방향을 탐색할 수 있게 한다.

청소할 수 있는 칸이 있으면 청소를 한다.

여기서는 청소한 칸을 2로 두어 다시 방문할 수는 있지만 다시 청소할 수 없게 한다.

그리고 그 칸으로 가야 하기 때문에 한 번만 실행한다.

만약 네 방향 모두 청소를 할 수 없으면 (cnt가 4일 때), 네 번 회전했으므로 현재 칸에 처음 들어왔을 때 상태이다.

그러므로 2번 회전한 (dir+2) 값은 로봇 한 칸 뒤 이므로 로봇의 값을 한 칸 후진한 칸으로 바꿔준다.

만약 한 칸 뒤가 벽이라면 로봇 작동을 멈춘다.

 

 

코드

#include <iostream>
#include <vector>
using namespace std;

int N, M;
vector<int>robot(3,0);
vector<vector<int>>Arr;
vector<pair<int, int>>loc = { { 0,-1 }, {1, 0}, {0, 1}, {-1, 0}  };
int clean_cnt;

void Clean() {
	if (Arr[robot[0]][robot[1]] == 0) clean_cnt++;
	Arr[robot[0]][robot[1]] = 2;

	while (1) {
		int dir = robot[2];
		int cnt = 0;
		for (cnt = 0; cnt < 4; ++cnt) {
			dir = robot[2];
			int n_y = robot[0] + loc[dir].first;
			int n_x = robot[1] + loc[dir].second;
			if (n_y >= 0 && n_y < N && n_x >= 0 && n_x < M) {
				if (Arr[n_y][n_x] == 0) {
					Arr[n_y][n_x] = 2;
					robot[0] = n_y;
					robot[1] = n_x;
					robot[2] = (dir + 1) % 4;
					clean_cnt++;
					break;
				}
				else {
					robot[2] = (dir + 1) % 4;
				}
			}
		}
		if (cnt == 4) {
			robot[0] += loc[(dir + 2) % 4].first;
			robot[1] += loc[(dir + 2) % 4].second;
			if (Arr[robot[0]][robot[1]] == 1)
				return;
		}
	}
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	int y = 0, x = 0;
	cin >> N >> M;
	cin >> robot[0] >> robot[1] >> robot[2];
	Arr = vector<vector<int>>(N, vector<int>(M, 0));
	
	robot[2] = (4 - robot[2]) % 4;	

	for (y = 0; y < N; ++y) {
		for (x = 0; x < M; ++x) {
			cin >> Arr[y][x];
		}
	}
	Clean();
	cout << clean_cnt;
}