[BOJ][백준 14503] 로봇 청소기 - C++
2023. 3. 24. 13:35ㆍIT이모) 알고리즘 문제풀이/백준 문제풀이
https://www.acmicpc.net/problem/14503
14503번: 로봇 청소기
첫째 줄에 방의 크기 $N$과 $M$이 입력된다. $(3 \le N, M \le 50)$ 둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 $(r, c)$와 처음에 로봇 청소기가 바라보는 방향 $d$가 입력된다. $d$가 $0$인 경우 북쪽
www.acmicpc.net
백준 사이트의 14503번 문제, 로봇 청소기 문제다.
본인은 C++로 문제풀이를 진행하였다.
0. 문제 읽기
로봇 청소기 작동 방식은 다음과 같다.
- 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
- 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우,
-> 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
-> 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
- 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우,
-> 반시계 방향으로 90도 회전한다.
-> 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다.
1번으로 돌아간다.
1. 문제풀이 아이디어
- 규칙대로 갈 수 있는 최대까지 이동하게 하는 단순 구현.
- 인자로 청소기의 방향을 가져가자.
- 그냥 작동 규칙대로 쭉 구현하면 될듯.
2. 코드 핵심 부분
1) 문제 풀이의 전부인 solve함수,
구현이 전부인 문제이고 특별한 알고리즘이 필요없어서 이 함수가 문제풀이의 전부다.
주석을 보면 알 수 있듯이 작동 규칙을 그대로 가져와 이를 코드로 구현했다.
// 문제풀이 함수
int solve() {
int Cnt = 0;
while (1) {
// 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
if (Map[Sy][Sx] == 0) {
Cnt++;
Map[Sy][Sx] = 2;
continue;
}
int temp = Dir;
int flag = 0;
// 주변 4칸 체크 (반시계 방향으로)
for (int i = 0; i < 4; i++) {
Dir = (Dir + 3) % 4;
int ny = Sy + diry[Dir];
int nx = Sx + dirx[Dir];
if (Map[ny][nx] == 0) {
flag = 1;
Sy = ny, Sx = nx;
break;
}
}
// 청소되지 않은 빈 칸이 없는 경우
if (flag == 0) {
Dir = (Dir + 2) % 4;
int ny = Sy + diry[Dir];
int nx = Sx + dirx[Dir];
// 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
if (Map[ny][nx] != 1) {
Sy = ny, Sx = nx;
Dir = temp;
}
// 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
else {
break;
}
}
}
return Cnt;
}
3. 전체 코드
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
/*
1. 문제읽기 (로봇청소기 작동방식)
현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우,
바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우,
반시계 방향으로 90도 회전한다.
바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다.
1번으로 돌아간다.
*/
/*
2. 아이디어
규칙대로 갈 수 있는 최대까지 이동하게 하는 단순 구현.
인자로 청소기의 방향을 가져가자.
그냥 규칙대로 쭉 구현하면 될듯.
*/
// 필요 인자들
int N, M; // 세로, 가로 (3 <= N, M <= 50)
int Sy, Sx, Dir; // 로봇위치, 방향
int Map[50][50];
// 방향배열 (북 동 남 서)
int diry[] = { -1, 0, 1, 0 };
int dirx[] = { 0, 1, 0, -1 };
// 값 입력받는 함수
void input() {
cin >> N >> M;
cin >> Sy >> Sx >> Dir;
for (int i = 0; i < N; i++) {
for (int j = 0; j < M; j++) {
cin >> Map[i][j];
}
}
}
// 문제풀이 함수
int solve() {
int Cnt = 0;
while (1) {
// 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
if (Map[Sy][Sx] == 0) {
Cnt++;
Map[Sy][Sx] = 2;
continue;
}
int temp = Dir;
int flag = 0;
// 주변 4칸 체크 (반시계 방향으로)
for (int i = 0; i < 4; i++) {
Dir = (Dir + 3) % 4;
int ny = Sy + diry[Dir];
int nx = Sx + dirx[Dir];
if (Map[ny][nx] == 0) {
flag = 1;
Sy = ny, Sx = nx;
break;
}
}
// 청소되지 않은 빈 칸이 없는 경우
if (flag == 0) {
Dir = (Dir + 2) % 4;
int ny = Sy + diry[Dir];
int nx = Sx + dirx[Dir];
// 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
if (Map[ny][nx] != 1) {
Sy = ny, Sx = nx;
Dir = temp;
}
// 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
else {
break;
}
}
}
return Cnt;
}
// 메인함수
int main() {
// input
input();
// solve
int Ans = solve();
// output
cout << Ans << "\n";
return 0;
}
4. 문제 풀이를 마치며..
오랜만에 시뮬레이션, 구현 문제를 풀게되었다.
많은 학생들이 시뮬레이션 문제를 싫어하는데 그 이유는,
1) 문제가 보통 길다. 2) 코드가 길어질 수 밖에 없다. 3) 길어지고 정형화되어 있지 않은 만큼 디버깅이 어렵다.
이런 이유들이 있다.
시뮬레이션 문제의 핵심을 나는 침착하게 문제를 우선 다 읽고 상황을 이해한 뒤에 코드로 들어가는 것이라 생각한다.
그래야 실수가 나오지않고, 힘들게 디버깅하는 수고도 줄일 수 있다.
그렇게 정확히 읽고 이해한 정보들을 토대로 코드를 구현한다면 풀어낼 수 있을 것이다.
'IT이모) 알고리즘 문제풀이 > 백준 문제풀이' 카테고리의 다른 글
[BOJ][백준 14890] 경사로 - C++ (0) | 2023.03.27 |
---|---|
[BOJ][백준 14499] 주사위 굴리기 - C++ (0) | 2023.03.24 |
[BOJ][백준 14501] 퇴사 - C++ (0) | 2023.03.23 |
[BOJ][백준 16236] 아기 상어 - C++ (0) | 2023.03.21 |
[BOJ][백준 16637] 괄호 추가하기 - C++ (0) | 2023.03.17 |