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

혀니앤·2022년 10월 22일
0

C++ 알고리즘

목록 보기
116/118

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

1. 접근

  • 단순하게 모든 행동을 구현하면 된다
  • 컨베이어 벨트로 회전하게 되어있지만, 굳이 다른 자료구조를 쓸 필요 없이 vector를 써도 된다
    -> 대신 이 경우 컨베이어 벨트의 회전에서 erase와 insert 사용에 주의해야 한다
  • 로봇은 먼저 올려진 순서대로 이동한다. -> list를 써서 가장 앞의 값부터 접근한다.
    -> 내려질 위치에 도달하면 pop_front() 를 해주면 간단하게 처리된다
  • 현재의 컨베이어 벨트의 내구도, 현재 어떤 위치에 로봇이 위치하는지, 각 로봇이 어떤 위치에 있는지를 저장할 3개의 데이터가 필요하다

✔️ vector erase 사용 시 iter++ 주의

iter vector.erase() 반환한 다음 iter를 반환한다

iter++ 사용에 주의해야 한다

  • for문과 함께 사용할 시 노드가 더이상 없어 iter = vector.end() 인 상태에서 iter++ 가 되면서 에러가 발생한다
  • iter—를 해주어 기존 노드를 가리키게 해두었는데, iter++가 되면서 한 노드를 건너뛴다

2. 나의 풀이

#include <iostream>
#include <vector>
#include <list>
using namespace std;
int main() {
	ios::sync_with_stdio(false);
	cin.tie(NULL);
	cout.tie(NULL);

	int N, K;
	cin >> N >> K;

	vector<int> rail; //현재 레일의 내구도를 저장하는 배열
	list<int> robot; //로봇을 순서대로 기록한 리스트
	vector<bool> onuse(N * 2); //쓰이고 있다면 True값을 가진다

	for (int i = 0; i < N * 2; i++) {
		int input;
		cin >> input;
		rail.push_back(input);
	}
	
	int t = 1;
	while (1) {
		//1. 벨트의 로봇을 한 칸씩 회전시킨다
		fill(onuse.begin(), onuse.end(), false);
		//레일을 한번 회전시켜준다 = vector의 맨 뒷값을 가장 앞에 insert 해준다
		rail.insert(rail.begin(),rail[2*N-1]);
		rail.erase(rail.end()-1);

		for (auto iter = robot.begin(); iter != robot.end();) {
			*iter = (*iter+1)%(2*N);
			if (*iter == N-1) { //내리는 레일에 도달하면 내리기
				iter = robot.erase(iter);
				if(iter!=robot.begin()) iter--;
				if (robot.size() == 0)	break;
				continue;
			}
			onuse[*iter] = true;
			iter++;
		}

		//2. 가장 먼저 놓은 로봇부터 로봇을 한칸씩 이동시킨다
		for (auto iter = robot.begin(); iter != robot.end();) {
        //다른 로봇이 올라가있는지 / 레일의 내구도가 있는지 확인한다
			if (!onuse[*iter + 1]&&rail[(*iter+1)%(2*N)]>0) {
				onuse[*iter] = false;
				*iter = (*iter + 1) % (2 * N);
				rail[*iter]--;
				if (*iter == N-1) { //내리는 레일에 도달하면 내리기
					iter = robot.erase(iter);
					if (iter != robot.begin()) iter--;
					if (robot.size() == 0)	break;
					continue;
				}

				onuse[*iter] = true;
			}
			iter++;
		}
		//3. 올리는 위치(0번 인덱스)에 로봇을 하나 올린다
		if (!onuse[0] && rail[0] > 0) {
			rail[0]--;
			onuse[0] = true;
			robot.push_back(0);
		}
		//4. 내구도가 0인 칸의 개수가 K개 이상이라면, 종료한다
		int count = 0;
		for (int i = 0; i < rail.size(); i++) {
			if (rail[i] == 0)	count++;
		}
		if (count >= K) {
			cout << t << "\n";
			return 0;
		}
		t++;
	}
	return 0;
}

채점 결과

profile
일단 시작하기

0개의 댓글