반응형
https://www.acmicpc.net/problem/14503
💡 로봇 청소기
✅ 문제 풀이
문제를 풀기 전에 지문을 완벽하게 해석해야 한다. 질문게시판을 보면 알겠지만, 문제 해석에 어려움이 많아보인다.
- 로봇청소기는 입력으로 주어지는 (r,c)에서 출발하고 방향도 입력으로 주어지는 d를 향하여 시작한다.
- 이때 d는 북쪽일 경우 0, 동쪽일 경우 1, 남쪽일 경우 2, 서쪽일 경우 3이다.
나는 여기서 동쪽과 서쪽을 반대로 생각하는 실수로 인해 자꾸 틀렸습니다가 떠서 알고리즘의 문제인가 싶었다.. - 방의 상태는 2차원 arr벡터에, 청소를 한 칸의 횟수는 count에 저장한다.
- 그리고 다음 과정을 while문을 통해서 반복해주면 된다.
- 현재 칸이 청소가 안되어 있으면, 즉 0이면 count를 하나 증가시켜주고 현재 칸의 값을 2로 바꾸어준다.
2로 하는 이유는 청소가 안된 0과 벽인 1을 구분하기 위함이다. - 그리고 현재 칸에서 동서남북에 있는 칸 중 청소가 안된 칸이 있는지 확인한다. 이때 어디가 청소가 안된 칸인지 정확히 알 필요는 없다. 그냥 청소가 안된 칸이 있다면 bool타입의 clean을 false로 바꾸어주면 된다.
- 만약(if) 현재 칸에서 동서남북에 있는 칸 중 청소가 안된 칸이 없다면 clean이 true일 것이다. 따라서 clean이 true이면 다음을 따른다.
3-A. 만약(if) 현재 방향에서 한칸 뒤가 벽이 아니라면, 즉 1이 아니라면 후진할 수 있는 것이기 때문에 r과 c를 한칸 후진한 좌표로 갱신해준다. 이 로직을 수행하고 나면 다시 while문의 1번으로 돌아가게 될 것이다.
3-B. 만약 현재 방향에서 한칸 뒤가 벽이라면(else), 즉 1이라면 현재 상태에서 청소를 멈춘다. 따라서 count를 출력하고 return 0;을 함으로써 while문을 끝내고 프로그램을 종료한다. - 3과 같지 않다면(else), 즉 주변에 청소할 칸이 하나라도 있으면 clean이 false일 것이다. 따라서 clean이 false이면 다음을 따른다.
4-A. 무조건 현재 방향에서 왼쪽(반시계방향)으로 90도 돌린다. 즉 현재 방향이 북이라면 서로, 서라면 남으로, 남이라면 동으로, 동이라면 북으로 돌아간다. 따라서 숫자로 보면 0>>3>>2>>1>>0...방향이다.
이는 (d+3)을 4로 나눈 나머지와 같아진다. 따라서 d를 (d+3)%4로 갱신해 주면 된다.
4-B. 그리고 갱신된 방향으로 한칸 앞이 청소가 안되어 있으면 r과 c를 한칸 앞인 좌표로 갱신해준다. 이 로직을 수행하고 나면 다시 while문의 1번으로 돌아가게 될 것이다. - while문을 끝내고 난 뒤에는 count를 출력하도록 한다.
✏ 코드 전문
#include<iostream>
#include<vector>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
int n, m;
cin >> n >> m;
int r, c, d;
cin >> r >> c >> d;
vector<vector<int>> arr(n, vector<int> (m));
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
cin >> arr[i][j];
}
}
int count = 0;
int dx[] = { -1,1,0,0 };
int dy[] = { 0,0,-1,1 };
while (1) {
if (arr[r][c] == 0) {//현재 위치가 벽이 아니고, 청소가 안된 곳이라면
count++;
arr[r][c] = 2;//청소를 완료하면 2로 채운다
}
bool clean = true;
for (int i = 0; i < 4; i++) {
int x = r + dx[i];
int y = c + dy[i];
if (arr[x][y] == 0) {
clean = false;//하나라도 청소안된 곳이있으면 바로 빠져나옴
break;
}
}
if (clean) {//주변에 청소할데가 없으면
int bx, by;
if (d == 0) {//북
bx = r + 1;
by = c;
}
else if (d == 1) {//동
bx = r;
by = c - 1;
}
else if (d == 2) {//남
bx = r - 1;
by = c;
}
else {//서
bx = r;
by = c + 1;
}
if (arr[bx][by] != 1) {//후진할 수 있으면
r = bx;
c = by;
}
else {
cout << count;
return 0;//중단
}
}
//0>>3>>2>>1>>0
else{//청소할데가 있으면
d = (d + 3) % 4;//회전=반시례로 90도는 시계로 270도니까
if (d == 0) {//북
if (arr[r - 1][c] == 0) {
r = r - 1;
}
}
else if (d == 1) {//동
if (arr[r][c + 1] == 0) {
c = c + 1;
}
}
else if (d == 2) {//남
if (arr[r + 1][c] == 0) {
r = r + 1;
}
}
else {//서
if (arr[r][c - 1] == 0) {
c = c - 1;
}
}
}
}
cout << count;
return 0;
}
반응형
'CO-TE > 백준' 카테고리의 다른 글
[백준] 11660번 C++ "구간 합 구하기 5" 풀이 / 누적합, 2차원 벡터 (1) | 2023.12.22 |
---|---|
[백준] 2667번 C++ "단지번호붙이기" 풀이 / DFS 알고리즘 (1) | 2023.12.20 |
[백준] 1991번 C++ "트리 순회" 풀이 / 트리, 전위-중위-후위 순회 (0) | 2023.12.17 |
[백준] 2178번 C++ "미로 탐색" 풀이 / BFS 알고리즘, 그래프 알고리즘 (1) | 2023.12.15 |
[백준] 1004번 C++ "어린 왕자" 풀이 / 기하학 접근법 (0) | 2023.12.13 |