이것저것

BOJ - 2346. 풍선 터뜨리기 본문

Problem Solving

BOJ - 2346. 풍선 터뜨리기

nays111 2021. 1. 10. 06:33

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은 적혀있지 않다고 가정하자.

출력

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

예제 입력 1

5 3 2 1 -3 -1

예제 출력 1

1 4 5 3 2

사용할 자료구조

양수로 적혀 있을 경우에는 오른쪽으로 이동, 음수로 적혀 있을 경우에는 왼쪽으로 이동한다고 하였기 때문에 양방향으로 삽입/삭제가 가능한 Deque를 사용해야한다고 떠올렸습니다. (+ 풍선은 원형으로 놓여있다고 생각하라고 했기 때문에)

풀이 과정

  1. 풍선 인덱스와 풍선 안에 적혀있는 숫자가 Deque안에 세트로 담겨야하므로 pair 클래스를 사용했습니다.

deque<pair<int, int>> dq //첫번째 int는 풍선 인덱스, 두번째 int는 풍선 안에 적혀있는 숫자

  1. 풍선 안에 적혀있는 숫자를 미리 frontNum이라는 변수에 저장해두고 이 frontNum이 양수인지 음수인지에 따라서 이동 방향을 다르게 설정해주면 됩니다.

int frontNum = dq.front().second;

  1. 필요한 연산 3가지

3-1) deque의 가장 앞에 있는 풍선만 터뜨릴 수 있습니다. (+ 떠뜨린 풍선 인덱스 출력)

cout<<dq.front().first<<" "; dq.pop_front();

3-2) 양수가 적혀있을 경우에는 풍선안에 들어 있는 숫자 -1 만큼 오른쪽으로 이동

for(int i=0;i<frontNum-1;i++){ dq.push_back(dq.front()); dq.pop_front(); }

3-3) 음수가 적혀있을 경우에는 abs(풍선안에 들어 있는 숫자) 만큼 왼쪽으로 이동

for(int i=0;i<abs(frontNum);i++){ dq.push_front(dq.back()); dq.pop_back(); }

처음에 양수가 적혀있을 경우에도 frontNum 만큼만 이동하면 되는 줄 알았는데 , 풍선을 터뜨렸을 때, 빈 공간이 채워지면서 한 칸 미리 이동한 것과 같다. 그러므로 -1 을 추가해줘야함.

시간 복잡도

Deque 에서 삽입/삭제/탐색 연산은 모두 O(1) 만큼 걸린다.

Deque가 n만큼 순회하면서 frontNum만큼 연산을 하였기 때문에 O(n*frontNum) 이라고 생각한다. (?)

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <cstdio>
#include <stack>
#include <queue>
#include <map>
#include <functional>
using namespace std;

int main(){
    cin.tie(0);
    cout.tie(0);
    ios::sync_with_stdio(false);
    int n;
    cin>>n;
    deque<pair<int,int>> dq;
    for(int i=1;i<=n;i++){
        int a;
        cin>>a;
        dq.push_back(make_pair(i,a));
    }
    while(!dq.empty()){

        int frontNum = dq.front().second;
        cout<<dq.front().first<<" ";
        dq.pop_front();
        if(frontNum>0 && !dq.empty()){
            for(int i=0;i<frontNum-1;i++){
                dq.push_back(dq.front());
                dq.pop_front();
            }
        }else if (frontNum<0 && !dq.empty()){
            for(int i=0;i<abs(frontNum);i++){
                dq.push_front(dq.back());
                dq.pop_back();
            }
        }
        
    }
}

 

'Problem Solving' 카테고리의 다른 글

BOJ - 1935. 후위표기식2  (0) 2021.01.10
BOJ - 1406. 에디터  (0) 2021.01.10
BOJ - 1158. 요세푸스 문제  (0) 2021.01.10
BOJ - 1021. 회전하는 큐  (0) 2021.01.09
BOJ - 1918. 후위 표기식  (0) 2021.01.09
Comments