[백준 알고리즘] 2346번: 풍선터뜨리기

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

문제

문제

N개의 풍선이 있다. 각 풍선 안에는 -N부터 N까지의 수가 적혀있는 종이가 들어 있다. 이 풍선들을 다음과 같은 규칙으로 터뜨린다.

우선, 제일 처음에는 1번 풍선을 터뜨린다. 다음에는 풍선 안에 있는 종이를 꺼내어 그 종이에 적혀있는 값만큼 이동하여 다음 풍선을 터뜨린다. 양수가 적혀 있을 경우에는 오른쪽으로, 음수가 적혀 있을 때는 왼쪽으로 이동한다. 풍선은 원형으로 놓여 있다고 생각한다. 즉, 1번 풍선의 왼쪽에 N번 풍선이 있고, N번 풍선의 오른쪽에 1번 풍선이 있는 것이다. 이동할 때에는 이미 터진 풍선은 빼고 생각한다.

예를 들어 다섯 개의 풍선 안에 차례로 3, 2, 1, -3, -1이 적혀 있었다고 하자. 이 경우 3이 적혀 있는 1번 풍선, -3이 적혀 있는 4번 풍선, -1이 적혀 있는 5번 풍선, 1이 적혀 있는 3번 풍선, 2가 적혀 있는 2번 풍선의 순서대로 터지게 된다.

입력

첫째 줄에 자연수 N(1≤N≤1,000)이 주어진다. 다음 줄에는 차례로 각 풍선 안의 종이에 적혀 있는 수가 주어진다. 편의상 0은 적혀있지 않다고 가정하자.

출력

첫째 줄에 터진 풍선의 번호를 차례로 나열한다.

풀이

Double Ended Queue 라는 이름에 걸맞게, 덱으로 풀면 쉽사리 풀 수 있는 문제였다. 덱은 중간 삽입이나 다이나믹 어세스가 필요한 상황이 아니라면 항상 O(1) 의 속도를 보장하는 앞뒤 값 사용에는 무적인 자료구조이다.

페어로 인덱스를 저장해두었는데, 계속 메모리 초과가 나서 고생을 좀 했다. 이유는 내가 반복문에서 부필요한 변수를 사용해서였다. dq.front() 값을 따로 저장하지 않고 그대로 push_back 의 인자로 넣어주었더니 정답처리를 받았다.

코드

#include <iostream>
#include <deque>

using namespace std;

int main() {
    int N;
    cin >> N;
    deque<pair<int, int>> dq;
    for (int i = 1; i <= N; i++) {
        int n;
        cin >> n;
        dq.push_back({ n, i });
    }

    while (!dq.empty()) {
        auto next = dq.front();
        dq.pop_front();

        cout << next.second << " ";

        if (next.first > 0) {
            for (int i = 0; i < next.first - 1; i++) {
                dq.push_back(dq.front());
                dq.pop_front();
            }
        }
        else {
            next.first *= -1;
            for (int i = 0; i < next.first; i++) {
                dq.push_front(dq.back());
                dq.pop_back();

            }
        }
    }
}

Written by@전여훈 (Click Me!)
고민이 담긴 코드를 만들자, 고민하기 위해 공부하자.