728x90
반응형
https://www.acmicpc.net/problem/14503
14503번: 로봇 청소기
첫째 줄에 방의 크기 $N$과 $M$이 입력된다. $(3 \le N, M \le 50)$ 둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 $(r, c)$와 처음에 로봇 청소기가 바라보는 방향 $d$가 입력된다. $d$가 $0$인 경우 북쪽
www.acmicpc.net

시뮬레이션, 구현 문제
지문을 잘 읽고 적힌 그대로 구현하면 된다.
조건 체크 함수를 구현하고 로봇 청소기를 작동시키는 하나의 함수에서 모든 작업을 수행하였다.
1. 입력부 메인 함수
<cpp />
int main() {
int n, m; cin >> n >> m;
// -1 = 청소 O, 0 = 청소 X, 1 = 벽
// dir :: 0 - 상 / 1 - 우 / 2 - 하 / 3 - 좌
vector <vector <int>> vc(n, vector <int>(m, 0));
int startX, startY;
cin >> startX >> startY >> dir;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> vc[i][j];
}
}
cout << CleanTheRoom(vc, startX, startY);
}
2. 로봇 청소기 작동 함수
<cpp />
int CleanTheRoom(vector <vector <int>>& room, int nowX, int nowY) {
int CleaningCount = 0;
while (1) {
// 1. 현재칸이 청소되지 않은 경우 현재 칸을 청소한다.
if (room[nowX][nowY] == 0) {
room[nowX][nowY] = -1;
CleaningCount++;
}
else {
// 2. 현재 칸의 주변 4칸 중 청소되지 않은 빈칸이 없는 경우
if (!CanICleaning(room, nowX, nowY)) {
int nX = nowX - dx[dir];
int nY = nowY - dy[dir];
// 2-1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있는가?
if (IsValid(room, nX, nY) && CanIReverse(room, nX, nY)) {
// 후진할 수 있다면 한 칸 후진 후 1번으로 돌아간다.
nowX = nX;
nowY = nY;
}
// 후진 할 수 없다면 종료
else {
return CleaningCount;
}
}
// 3. 현재 칸의 주변 4칸 중 청소되지 않은 빈칸이 있는 경우
else if (CanICleaning(room, nowX, nowY)) {
// 3-1. 반시계 방향으로 90도 회전한다.
RotateDir();
// 3-2. 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸이면 한 칸 전진
int nX = nowX + dx[dir];
int nY = nowY + dy[dir];
if (IsValid(room, nX, nY) && CanGo(room, nX, nY)) {
nowX = nX;
nowY = nY;
// 3-3. 아니라면 다시 방향을 회전한다.
}
}
}
}
}
3. 조건 체크 함수들
3-1) 방향을 나타내는 배열
<cpp />
int dir;
// 순서대로 상, 우, 하, 좌를 나타냄
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, 1, 0, -1 };
3-2) 반시계 방향으로 방향을 전환하는 함수
<cpp />
void RotateDir() {
if (dir > 0)
dir--;
else if (dir == 0)
dir = 3;
}
3-3) 해당 방향으로 이동할 수 있는지 확인하는 함수
<cpp />
bool CanGo(vector <vector <int>>& room, int nX, int nY) {
if (room[nX][nY] == 0)
return true;
return false;
}
3-4) 배열 범위를 벗어나지 않는지 확인하는 함수
<cpp />
bool IsValid(vector <vector <int>>& room, int nX, int nY) {
if (nX < 0 || nY < 0 || nX >= room.size() || nY >= room[0].size())
return false;
return true;
}
3-5) 뒤로 이동할 수 있는지 확인하는 함수
<cpp />
bool CanIReverse(vector <vector <int>>& room, int nX, int nY) {
// 2-1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있는가?
// -> 한 칸 후진 했을 때 벽이 아닌가?
if (room[nX][nY] != 1) {
return true;
}
return false;
}
3-6) 현재 위치 기준 주변 4칸 중 청소되지 않은 칸을 확인하는 함수
<cpp />
bool CanICleaning(vector <vector <int>>& room, int nowX, int nowY) {
for (int i = 0; i < 4; i++) {
int nX = nowX + dx[i];
int nY = nowY + dy[i];
if (IsValid(room, nX, nY)) {
if (room[nX][nY] == 0)
return true;
}
}
return false;
}
전체 코드
<cpp />
#include <bits/stdc++.h>
using namespace std;
int dir;
// 상, 우, 하, 좌
int dx[4] = { -1, 0, 1, 0 };
int dy[4] = { 0, 1, 0, -1 };
void Print(vector <vector <int>>& room) {
for (int i = 0; i < room.size(); i++) {
for (int j = 0; j < room[0].size(); j++) {
cout << room[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
void RotateDir() {
if (dir > 0)
dir--;
else if (dir == 0)
dir = 3;
}
bool CanGo(vector <vector <int>>& room, int nX, int nY) {
if (room[nX][nY] == 0)
return true;
return false;
}
// 범위를 벗어나지 않는지 확인
bool IsValid(vector <vector <int>>& room, int nX, int nY) {
if (nX < 0 || nY < 0 || nX >= room.size() || nY >= room[0].size())
return false;
return true;
}
bool CanIReverse(vector <vector <int>>& room, int nX, int nY) {
// 2-1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있는가?
// -> 한 칸 후진 했을 때 벽이 아닌가?
if (room[nX][nY] != 1) {
return true;
}
return false;
}
// 주변 4칸 중 청소되지 않은 칸이 있는지 확인
bool CanICleaning(vector <vector <int>>& room, int nowX, int nowY) {
for (int i = 0; i < 4; i++) {
int nX = nowX + dx[i];
int nY = nowY + dy[i];
if (IsValid(room, nX, nY)) {
if (room[nX][nY] == 0)
return true;
}
}
return false;
}
int CleanTheRoom(vector <vector <int>>& room, int nowX, int nowY) {
int CleaningCount = 0;
while (1) {
// 1. 현재칸이 청소되지 않은 경우 현재 칸을 청소한다.
if (room[nowX][nowY] == 0) {
room[nowX][nowY] = -1;
CleaningCount++;
}
else {
// 2. 현재 칸의 주변 4칸 중 청소되지 않은 빈칸이 없는 경우
if (!CanICleaning(room, nowX, nowY)) {
int nX = nowX - dx[dir];
int nY = nowY - dy[dir];
// 2-1. 바라보는 방향을 유지한 채로 한 칸 후진할 수 있는가?
if (IsValid(room, nX, nY) && CanIReverse(room, nX, nY)) {
// 후진할 수 있다면 한 칸 후진 후 1번으로 돌아간다.
nowX = nX;
nowY = nY;
}
// 후진 할 수 없다면 종료
else {
return CleaningCount;
}
}
// 3. 현재 칸의 주변 4칸 중 청소되지 않은 빈칸이 있는 경우
else if (CanICleaning(room, nowX, nowY)) {
// 3-1. 반시계 방향으로 90도 회전한다.
RotateDir();
// 3-2. 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸이면 한 칸 전진
int nX = nowX + dx[dir];
int nY = nowY + dy[dir];
if (IsValid(room, nX, nY) && CanGo(room, nX, nY)) {
nowX = nX;
nowY = nY;
// 3-3. 아니라면 다시 방향을 회전한다.
}
}
}
}
}
int main() {
int n, m; cin >> n >> m;
// -1 = 청소 O, 0 = 청소 X, 1 = 벽
// dir :: 0 - 상 / 1 - 우 / 2 - 하 / 3 - 좌
vector <vector <int>> vc(n, vector <int>(m, 0));
int startX, startY;
cin >> startX >> startY >> dir;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> vc[i][j];
}
}
cout << CleanTheRoom(vc, startX, startY);
}

728x90
반응형
'Algorithm' 카테고리의 다른 글
[BOJ/CPP] 아카라카 - 23304번 / C++ 풀이 (0) | 2023.12.08 |
---|---|
[BOJ/CPP] 고양이 카페 - 28353번 / C++ 풀이 (1) | 2023.10.30 |
[Programmers/Level2] 프로그래머스 - 짝지어 제거하기 [C++풀이] (0) | 2023.09.16 |
[BOJ/CPP] 부분합 - 1806번 / C++ 풀이 (0) | 2023.05.26 |
[BOJ/CPP] 빈도 정렬 - 2910번 / C++풀이 (0) | 2023.05.12 |