[Python] 백준 2841 외계인의 기타 연주 (Stack)
📌 문제
상근이의 상상의 친구 외계인은 손가락을 수십억개 가지고 있다. 어느 날 외계인은 기타가 치고 싶었고, 인터넷에서 간단한 멜로디를 검색했다. 이제 이 기타를 치려고 한다.
보통 기타는 1번 줄부터 6번 줄까지 총 6개의 줄이 있고, 각 줄은 P개의 프렛으로 나누어져 있다. 프렛의 번호도 1번부터 P번까지 나누어져 있다.
멜로디는 음의 연속이고, 각 음은 줄에서 해당하는 프렛을 누르고 줄을 튕기면 연주할 수 있다. 예를 들면, 4번 줄의 8번 프렛을 누르고 튕길 수 있다. 만약, 어떤 줄의 프렛을 여러 개 누르고 있다면, 가장 높은 프렛의 음이 발생한다.
예를 들어, 3번 줄의 5번 프렛을 이미 누르고 있다고 하자. 이때, 7번 프렛을 누른 음을 연주하려면, 5번 프렛을 누르는 손을 떼지 않고 다른 손가락으로 7번 프렛을 누르고 줄을 튕기면 된다. 여기서 2번 프렛의 음을 연주하려고 한다면, 5번과 7번을 누르던 손가락을 뗀 다음에 2번 프렛을 누르고 연주해야 한다.
이렇게 손가락으로 프렛을 한 번 누르거나 떼는 것을 손가락을 한 번 움직였다고 한다. 어떤 멜로디가 주어졌을 때, 손가락의 가장 적게 움직이는 회수를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 멜로디에 포함되어 있는 음의 수 N과 한 줄에 있는 프렛의 수 P가 주어진다. (N ≤ 500,000, 2 ≤ P ≤ 300,000)
다음 N개 줄에는 멜로디의 한 음을 나타내는 두 정수가 주어진다. 첫 번째 정수는 줄의 번호이고 두 번째 정수는 그 줄에서 눌러야 하는 프렛의 번호이다. 입력으로 주어진 음의 순서대로 기타를 연주해야 한다.
출력
첫째 줄에 멜로디를 연주하는데 필요한 최소 손가락 움직임을 출력한다.
예제 입력 1
5 15
2 8
2 10
2 12
2 10
2 5
예제 출력 1
7
예제 입력 2
7 15
1 5
2 3
2 5
2 7
2 4
1 5
1 3
예제 출력 2
9
📌 풀이
import sys
input = sys.stdin.readline
n, p = map(int, input().split())
lines = [[] for _ in range(7)]
cnt = 0
for _ in range(n):
line, fret = map(int, input().split())
line = lines[line - 1]
while line and fret < line[-1]:
line.pop()
cnt += 1
if not line or fret > line[-1]:
line.append(fret)
cnt += 1
print(cnt)
한 줄에 눌려있는 프렛 번호를 저장하기 위해 stack을 사용하고, 줄이 여러개이기 때문에 stack들의 리스트를 만들어 사용한다.
- line: 해당 줄 stack
- fret: 현재 누르려는 프렛 번호
stack 상태의 경우의 수를 살펴 보면 크게 아래 7개의 경우가 있다.
우리가 취해야 할 동작은 pop이거나 append이거나 둘 중 하나이므로, pop이 필요한 경우와 append가 필요한 경우를 이분법적으로 나눠 보면 아래와 같다.
- while line and fret < line[-1]
stack이 차 있고 stack top이 누르려는 프렛보다 큰 번호인 경우 pop - if not line or fret > line[-1]
stack이 비어 있거나 stack top이 누르려는 프렛보다 작은 번호인 경우 append
Author And Source
이 문제에 관하여([Python] 백준 2841 외계인의 기타 연주 (Stack)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@hygge/Python-백준-2841-외계인의-기타-연주-Stack저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)