문제 링크
https://www.acmicpc.net/problem/2346
2346번: 풍선 터뜨리기
1번부터 N번까지 N개의 풍선이 원형으로 놓여 있고. i번 풍선의 오른쪽에는 i+1번 풍선이 있고, 왼쪽에는 i-1번 풍선이 있다. 단, 1번 풍선의 왼쪽에 N번 풍선이 있고, N번 풍선의 오른쪽에 1번 풍선
www.acmicpc.net
시간 제한 / 메모리 제한
2 초 | 4 MB |
문제
1번부터 N번까지 N개의 풍선이 원형으로 놓여 있고. i번 풍선의 오른쪽에는 i+1번 풍선이 있고, 왼쪽에는 i-1번 풍선이 있다. 단, 1번 풍선의 왼쪽에 N번 풍선이 있고, N번 풍선의 오른쪽에 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은 적혀있지 않다.
출력
첫째 줄에 터진 풍선의 번호를 차례로 나열한다.
예제 입력
5
3 2 1 -3 -1
예제 출력
1 4 5 3 2
문제 풀이를 위해 생각한 것
- 원형으로 회전하기 위해서 덱 자료구조를 써야 한다.
- 풍선을 터트리고 나온 수의 절댓값 - 1번 만큼, 양수면 왼쪽으로 음수면 오른쪽으로 덱을 회전한다.
- pop()연산은 항상 덱의 가장 왼쪽에서 수행한다.
사용한 자료구조
덱.
이유는?
문제의 요구조건에 맞게 데이터를 회전시키기 위해서.
배열과 달리 데이터의 삽입 삭제가 O(1)이다.
풀이 코드
n = 첫 입렧값을 정수로 변환
d = 덱 자료구조 선언
res = 결과를 담을 배열 선언
temp = 풍선 안의 들어갈 종이 입력을 받아 배열에 할당
1부터 n까지 풍선번호 i에 대하여:
d.append((i, temp[i-1])) # 튜플의 형태로 (풍선번호, 종이) 저장
b, p = d.popleft() # 첫 풍선 터트리기
res.append(b)
while True:
if d의 길이가 1이면:
res.append(d.popleft()[0])
break
if p > 0:
p - 1번 동안:
d.append(d.popleft()) #덱의 왼쪽 회전
elif p < 0:
p의 절댓값 - 1 동안:
d.appendleft(d.pop()) # 덱의 오른쪽 회전
b, p = d.popleft()
res.append(b)
res 배열의 원소 r에 대하여:
print r
시간 복잡도 분석
O(N^2).
temp배열에 원소 추가 O(N).
덱에 원소 추가 O(N).
덱 회전 1회는 O(1).
"종이에는 -N보다 크거나 같고, N보다 작거나 같은 정수가 하나 적혀있다."
최악의 경우 N개의 원소마다 N번의 회전을 해야 하기에, 답을 도출하기까지 최악의 시간 복잡도는 O(N^2).
문제에서 중요한 부분
메모리 제한이 다른 문제에 비해 타이트하다.
덱을 두 방향으로 회전시키려면 각각 어떤 코드를 작성해야 하는지 생각해보아야 한다.
'CS > Problem-solving' 카테고리의 다른 글
백준 10799번 Pseudo code (0) | 2022.05.01 |
---|---|
백준 1874번 Pseudo code (0) | 2022.05.01 |
백준 1302번 Pseudo code (0) | 2022.05.01 |
백준 3986번 Pseudo code (0) | 2022.05.01 |
백준 1764번 Pseudo code (0) | 2022.05.01 |
댓글