[BOJ][백준 20055] 컨베이어 벨트 위의 로봇 - C++

2023. 4. 7. 16:47IT이모) 알고리즘 문제풀이/백준 문제풀이

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

 

20055번: 컨베이어 벨트 위의 로봇

길이가 N인 컨베이어 벨트가 있고, 길이가 2N인 벨트가 이 컨베이어 벨트를 위아래로 감싸며 돌고 있다. 벨트는 길이 1 간격으로 2N개의 칸으로 나뉘어져 있으며, 각 칸에는 아래 그림과 같이 1부

www.acmicpc.net

백준 사이트의 20055번 문제, 컨베이어 벨트 위의 로봇 문제다.

본인은 C++로 문제풀이를 진행하였다.


0. 문제 읽기

로봇이 움직이는 컨베이어 벨트

 

로봇을 옮기는 과정에서는 아래와 같은 일이 순서대로 일어난다.

  1. 벨트가 각 칸 위에 있는 로봇과 함께 한 칸 회전한다.
  2. 가장 먼저 벨트에 올라간 로봇부터, 벨트가 회전하는 방향으로 한 칸 이동할 수 있다면 이동한다. 만약 이동할 수 없다면 가만히 있는다.
    • 로봇이 이동하기 위해서는 이동하려는 칸에 로봇이 없으며, 그 칸의 내구도가 1 이상 남아 있어야 한다.
  3. 올리는 위치에 있는 칸의 내구도가 0이 아니면 올리는 위치에 로봇을 올린다.
  4. 내구도가 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형을 준비하는데 이 문제에 어려움을 느꼈다면

더욱 차분하게 단계별로 코드를 구현하는 연습을 해보자.

 

코드를 작성하기 전에 먼저 주석으로 기능을 나눠놓는 것이 도움이 될 것이다.