[c++] 백준 1021: 회전하는 큐

다미·2022년 10월 9일
0

백준

목록 보기
15/15

1021번: 회전하는 큐

◾ 문제

지민이는 N개의 원소를 포함하고 있는 양방향 순환 큐를 가지고 있다. 지민이는 이 큐에서 몇 개의 원소를 뽑아내려고 한다.

지민이는 이 큐에서 다음과 같은 3가지 연산을 수행할 수 있다.

  1. 첫 번째 원소를 뽑아낸다. 이 연산을 수행하면, 원래 큐의 원소가 a1,...,aka_1, ..., a_k이었던 것이 a2,...,aka_2, ..., a_k와 같이 된다.
  2. 왼쪽으로 한 칸 이동시킨다. 이 연산을 수행하면, a1,...,aka_1, ..., a_ka2,...,ak,a1a_2, ..., a_k, a_1이 된다.
  3. 오른쪽으로 한 칸 이동시킨다. 이 연산을 수행하면, a1,...,aka_1, ..., a_kak,a1,...,aa_k, a_1, ..., a이 된다.

큐에 처음에 포함되어 있던 수 N이 주어진다. 그리고 지민이가 뽑아내려고 하는 원소의 위치가 주어진다. (이 위치는 가장 처음 큐에서의 위치이다.) 이때, 그 원소를 주어진 순서대로 뽑아내는데 드는 2번, 3번 연산의 최솟값을 출력하는 프로그램을 작성하시오.

◾ 입력

첫째 줄에 큐의 크기 N과 뽑아내려고 하는 수의 개수 M이 주어진다. N은 50보다 작거나 같은 자연수이고, M은 N보다 작거나 같은 자연수이다. 둘째 줄에는 지민이가 뽑아내려고 하는 수의 위치가 순서대로 주어진다. 위치는 1보다 크거나 같고, N보다 작거나 같은 자연수이다.

◾ 출력

첫째 줄에 문제의 정답을 출력한다.


👀 코드

/**
 * baekjoon - 1021
 * deque
 */

#include <iostream>
#include <deque>
#include <vector>
#define fio ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr)
using namespace std;

int main(){
    fio;
    //input
    int n, m; cin >> n >> m;
    int num;
    deque<int> dq;
    vector<int> v;
    for (int i = 1; i <= n; i++){
        dq.push_back(i);
    }

    for (int i = 0; i < m; i++){
        cin >> num;
        v.push_back(num);
    }    

    //sol
    int answer = 0;
    int position;
    for (int i = 0; i < m; i++){

        for (int j = 0; j < n; j++){ // index find
            if(v[i] == dq.at(j)){
                position = j;
                break;
            }
        }

        if (position <= dq.size() / 2){
            for (int j = 0; j < position; j++){
                dq.push_back(dq.front());
                dq.pop_front();
                answer++;
            }
            dq.pop_front();
        }

        else {
            for (int j = 0; j < dq.size() - position; j++){
                dq.push_front(dq.back());
                dq.pop_back();
                answer++;
            }
            dq.pop_front();
        }

    }

    cout << answer;

    return 0;
}

📌 해설

해당 문제는 회전하는 큐를 구현하여 해결해주면 되는 문제이다. 따라서 회전하는 큐를 이용하기 위해서 deque를 사용하였다. 문제에는 1~3번 연산이 존재하는데 2번, 3번연산을 보게되면 다음과 같다.

2번 연산

왼쪽으로 한 칸 이동시킨다. 이 연산을 수행하면, a1,...,aka_1, ..., a_ka2,...,ak,a1a_2, ..., a_k, a_1이 된다.

3번 연산

오른쪽으로 한 칸 이동시킨다. 이 연산을 수행하면, a1,...,aka_1, ..., a_kak,a1,...,aa_k, a_1, ..., a이 된다.

둘의 연산이 최소인 경우를 구하기 위해서는 주어진 숫자가 어느 쪽으로 이동했을 때 더 적은지 판단할 필요가 있다. 따라서 현재 비교해야할 주어진 숫자의 위치를 구해야한다.

for (int j = 0; j < n; j++){
	if(v[i] == dq.at(j)){
		position = j; // position에 현재 주어진 숫자의 위치를 저장해줌.
		break;
	}
}

그리고 dq.size()를 2로 나누어서 주어진 숫자와 비교하여 어디에 가까운지 비교해줄 필요가 있다. 따라서 해당 조건문을 다음과 같이 적었다.

if (position <= dq.size() / 2){
            ...
}

그 후에 position을 deque의 첫번째 원소로 만들어주기 위해서 다음과 같이 원소를 앞 또는 뒤에 넣어준후 pop시켜 재정렬해준다.

if (position <= dq.size() / 2){ // 앞에 존재할 때
	for (int j = 0; j < position; j++){
		dq.push_back(dq.front());
		dq.pop_front();
		answer++;
	}
	dq.pop_front();
}

else { // 뒤에 존재할 때
	for (int j = 0; j < dq.size() - position; j++){
		dq.push_front(dq.back());
    dq.pop_back();
    answer++;
  }
	dq.pop_front();
}

해당 연산을 마치고 answer 값을 출력해주면 된다.

0개의 댓글