2023. 4. 7. 16:47ㆍIT이모) 알고리즘 문제풀이/백준 문제풀이
https://www.acmicpc.net/problem/20055
20055번: 컨베이어 벨트 위의 로봇
길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부
www.acmicpc.net
백준 사이트의 20055번 문제, 컨베이어 벨트 위의 로봇 문제다.
본인은 C++로 문제풀이를 진행하였다.
0. 문제 읽기
로봇을 옮기는 과정에서는 아래와 같은 일이 순서대로 일어난다.
- 벨트가 각 칸 위에 있는 로봇과 함께 한 칸 회전한다.
- 가장 먼저 벨트에 올라간 로봇부터, 벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다. 만약 이동할 수 없다면 가만히 있는다.
- 로봇이 이동하기 위해서는 이동하려는 칸에 로봇이 없으며, 그 칸의 내구도가 1 이상 남아 있어야 한다.
- 올리는 위치에 있는 칸의 내구도가 0이 아니면 올리는 위치에 로봇을 올린다.
- 내구도가 0인 칸의 개수가 K개 이상이라면 과정을 종료한다. 그렇지 않다면 1번으로 돌아간다.
종료되었을 때 몇 번째 단계가 진행 중이었는지 구해보자. 가장 처음 수행되는 단계는 1번째 단계이다.
1. 문제풀이 아이디어
- 정말정말 단순한 시뮬레이션 / 구현 문제
- 문제 이해가 어려울 수 있다. 차분하게 읽고 조건을 정확하게 봐서 실수하지 말자.
- 메인 함수에 while문으로 전체적인 코드 틀을 잡고 각 단계를 나눠서 각각 구현하자.
2. 코드 핵심 부분
1) 코드의 메인 함수,
워낙 단순한 구현 문제라 코드를 세세히 볼 필요는 없을 것 같다.
비슷한 문제가 나무 제태크 문제가 있었는데,
나무 제태크는 계절별로, 이 문제는 단계로 나뉘어 차례차례 계산이 실행된다는 공통점이 있다.
나는 문제를 풀때 메인함수를 먼저 쭉 작성하여 전체적인 프로그램의 틀을 잡는데,
이런 단계별로 나뉘어 작동하는 구현 문제를 풀 때 정말 좋은 방법이다.
// 메인함수
int main() {
// input
input();
// solve
while (1) {
Ans++;
// 1단계, 벨트가 각 칸 위에 있는 로봇과 함께 한 칸 회전한다.
rotateRobot();
// 2단계,벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다.
moveRobot();
// 3단계, 올리는 위치에 로봇을 올린다.
setRobot();
// 4단계, 내구도가 0인 칸의 개수가 K개 이상이라면 과정을 종료한다.
if (Cnt >= K)
break;
}
// output
cout << Ans;
return 0;
}
3. 전체 코드
#include <iostream>
#include <cstring>
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
/*
1. 문제읽기
*/
/*
2. 아이디어
*/
// 필요 인자들
int N; // 컨베이어 길이 (2 ≤ N ≤ 100)
int K; // 과정을 종료할 칸의 개수 (1 ≤ K ≤ 2N)
int Belt[2][100]; // 컨베이어 벨트 내구도
int Robot[2][100]; // 로봇 위치 기록
int Cnt; // 내구도가 0인 칸의 개수
int Ans; // 몇 번째 단계
// 값 입력받는 함수
void input() {
cin >> N >> K;
for (int i = 0; i < N; i++) {
cin >> Belt[0][i];
}
for (int i = 0; i < N; i++) {
cin >> Belt[1][N - i - 1];
}
}
void rotateRobot() {
// 규칙대로 내구도와 로봇 모두 한칸씩 회전시켜줌 (내구도 변화 X)
int tempB1 = Belt[0][N - 1];
int tempB2 = Belt[1][0];
int tempR1 = Robot[0][N - 1];
int tempR2 = Robot[1][0];
for (int i = N - 1; i >= 1; i--) {
Belt[0][i] = Belt[0][i - 1];
Belt[1][N - 1 - i] = Belt[1][N - i];
Robot[0][i] = Robot[0][i - 1];
Robot[1][N - 1 - i] = Robot[1][N - i];
}
Belt[1][N - 1] = tempB1;
Belt[0][0] = tempB2;
Robot[1][N - 1] = tempR1;
Robot[0][0] = tempR2;
// 내리는 위치 로봇 체크
if (Robot[0][N - 1])
Robot[0][N - 1] = 0;
}
void moveRobot() {
for (int i = N - 2; i >= 0; i--) {
// 로봇이 없는칸은 그냥 패스
if (!Robot[0][i])
continue;
// 옮길 수 있으면 로봇 옮겨주고 내구도 감소
if (!Robot[0][i + 1] && Belt[0][i + 1]) {
Robot[0][i] = 0;
Robot[0][i + 1] = 1;
Belt[0][i + 1]--;
// 내구도 0 체크
if (!Belt[0][i + 1])
Cnt++;
// 내리는 위치 로봇 체크
if (Robot[0][N - 1])
Robot[0][N - 1] = 0;
}
}
}
void setRobot() {
// 올리는 위치에 있는 칸의 내구도가 0이 아니면 올리는 위치에 로봇을 올린다.
if (Belt[0][0]) {
Robot[0][0] = 1;
Belt[0][0]--;
// 내구도 0 체크
if (!Belt[0][0])
Cnt++;
}
}
// 메인함수
int main() {
// input
input();
// solve
while (1) {
Ans++;
// 1단계, 벨트가 각 칸 위에 있는 로봇과 함께 한 칸 회전한다.
rotateRobot();
// 2단계,벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다.
moveRobot();
// 3단계, 올리는 위치에 로봇을 올린다.
setRobot();
// 4단계, 내구도가 0인 칸의 개수가 K개 이상이라면 과정을 종료한다.
if (Cnt >= K)
break;
}
// output
cout << Ans;
return 0;
}
4. 문제 풀이를 마치며..
이 문제를 풀기전에 플레5 난이도의 "큐빙"문제에 도전했는데,
정말 악랄한 구현문제였다.
반나절을 꼬박쓰고 별짓 다해서 그 문제를 풀고 난뒤에 푼 문제가 바로 이
20055번, "컨베이어 벨트 위의 로봇" 문제다.
힐링이 되는 난이도여서 행복했다.
만약 본인이 SW적성진단 A형을 준비하는데 이 문제에 어려움을 느꼈다면
더욱 차분하게 단계별로 코드를 구현하는 연습을 해보자.
코드를 작성하기 전에 먼저 주석으로 기능을 나눠놓는 것이 도움이 될 것이다.
'IT이모) 알고리즘 문제풀이 > 백준 문제풀이' 카테고리의 다른 글
[BOJ][백준 15486] 퇴사 2 - C++ (0) | 2023.04.13 |
---|---|
[BOJ][백준 2023] 신기한 소수 - C++ (0) | 2023.04.11 |
[BOJ][백준 16234] 인구 이동 - C++ (0) | 2023.04.05 |
[BOJ][백준 15685] 드래곤 커브 - C++ (0) | 2023.04.05 |
[BOJ][백준 15686] 치킨 배달 - C++ (0) | 2023.04.04 |