문제


상근이의 상상의 친구 외계인은 손가락을 수십억개 가지고 있다. 어느 날 외계인은 기타가 치고 싶었고, 인터넷에서 간단한 멜로디를 검색했다. 이제 이 기타를 치려고 한다.

보통 기타는 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개 줄에는 멜로디의 한 음을 나타내는 두 정수가 주어진다. 첫 번째 정수는 줄의 번호이고 두 번째 정수는 그 줄에서 눌러야 하는 프렛의 번호이다. 입력으로 주어진 음의 순서대로 기타를 연주해야 한다.

 

출력


첫째 줄에 멜로디를 연주하는데 필요한 최소 손가락 움직임을 출력한다.

 

예제 입력과 출력

 

 

알고리즘 분류


스택

 

정답

 

import sys
input = lambda : sys.stdin.readline().strip()

n, p=map(int,input().split())
a=[list(map(int,input().split())) for i in range(n)]

c=0
ch=[[] for i in range(7)]

for i,j in a:
    if len(ch[i]) == 0:
        ch[i].append(j)
        c +=1
        
    else:
        if j > ch[i][-1]:
            ch[i].append(j)
            c += 1
        elif j == ch[i][-1]: # 이미 있는 경우
            continue
        else: 
            while len(ch[i]) != 0 and j < ch[i][-1]:
                ch[i].pop()
                c += 1
            if len(ch[i]) != 0 and ch[i][-1] == j:
                continue
            ch[i].append(j)
            c += 1

print(c)

1. 기타의 각 줄에 대해 스택을 사용합니다.
2. i 줄의 스택이 비어있으면 값을 추가합니다.
3. i 줄의 스택이 비어있지 않은 경우 스택안의 값과 j 값을 비교합니다.
3-1. j가 스택의 값보다 더 큰 경우 스택에 값을 추가합니다.
3-2. j와 스택의 값이 같은 경우 추가사항 없이 넘어갑니다.
3-3. j가 스택의 값보다 작은 경우 스택의 끝에서부터 j보다 큰 값들을 모두 삭제합니다.
큰 값들을 모두 삭제하고 스택의 값과 j의 값이 같으면 추가사항 없이 넘어가고 그렇지 않으면
스택에 j를 추가합니다.
4. 각 과정마다 손가락 움직인 횟수를 더해 출력합니다.

 

예제 설명
1 5 : 1 스택의 5 누르기
2 3 : 2 스택의 3 누르기
2 5 : 2 스택의 5 누르기
2 7 : 2 스택의 7 누르기
2 4 : 2 스택의 7 떼기, 2 스택의 5 떼기, 2 스택의 4 누르기
1 5 : 넘어가기(1 스택에 5 있어서)
1 3 : 1 스택의 5 떼기, 1 스택의 3 떼기

따라서 필요한 손가락 움직임의 최소 횟수는 9입니다.

 


백준 알고리즘 2841번 : www.acmicpc.net/problem/2841

 

2841번: 외계인의 기타 연주

문제 상근이의 상상의 친구 외계인은 손가락을 수십억개 가지고 있다. 어느 날 외계인은 기타가 치고 싶었고, 인터넷에서 간단한 멜로디를 검색했다. 이제 이 기타를 치려고 한다. 보통 기타는 1

www.acmicpc.net

 

문제


이번 계절학기에 심리학 개론을 수강 중인 평석이는 오늘 자정까지 보고서를 제출해야 한다. 보고서 작성이 너무 지루했던 평석이는 노트북에 엎드려서 꾸벅꾸벅 졸다가 제출 마감 1시간 전에 깨고 말았다. 안타깝게도 자는 동안 키보드가 잘못 눌려서 보고서의 모든 글자가 A와 B로 바뀌어 버렸다! 그래서 평석이는 보고서 작성을 때려치우고 보고서에서 '좋은 단어'나 세보기로 마음 먹었다.

평석이는 단어 위로 아치형 곡선을 그어 같은 글자끼리(A는 A끼리, B는 B끼리) 쌍을 짓기로 하였다. 만약 선끼리 교차하지 않으면서 각 글자를 정확히 한 개의 다른 위치에 있는 같은 글자와 짝 지을수 있다면, 그 단어는 '좋은 단어'이다. 평석이가 '좋은 단어' 개수를 세는 것을 도와주자.

 

입력


첫째 줄에 단어의 수 N이 주어진다. (1 ≤ N ≤ 100)

다음 N개 줄에는 A와 B로만 이루어진 단어가 한 줄에 하나씩 주어진다. 단어의 길이는 2와 100,000사이이며, 모든 단어 길이의 합은 1,000,000을 넘지 않는다.

 

출력


첫째 줄에 좋은 단어의 수를 출력한다.

 

예제 입력과 출력

 

 

알고리즘 분류


스택
문자열 처리

정답

 

from collections import deque
import sys
input = lambda : sys.stdin.readline().strip()

n=int(input())
a=[list(input()) for i in range(n)]
c= 0
for i in a:
    li=deque()
    for j in i:
        if len(li) == 0:
            li.append(j)
        elif len(li) >= 1:
            if li[-1] == j:
                li.pop()
            else:
                li.append(j)
    
    if len(li) == 0:
        c +=1
        
print(c)

1. 첫번째 알파벳을 덱 li에 넣습니다.
2. 스택 맨 위의 알파벳과 넣을 알파벳이 같으면 pop을 하고 같지 않으면 push 합니다.
3. 덱의 길이가 0이면 좋은 단어 개수를 하나 올려줍니다.
4. 좋은 단어 개수를 출력합니다.

 


백준 알고리즘 3986번 : https://www.acmicpc.net/problem/3986

 

3986번: 좋은 단어

문제 이번 계절학기에 심리학 개론을 수강 중인 평석이는 오늘 자정까지 보고서를 제출해야 한다. 보고서 작성이 너무 지루했던 평석이는 노트북에 엎드려서 꾸벅꾸벅 졸다가 제출 마감 1시간 �

www.acmicpc.net

 

문제


스택 (stack)은 기본적인 자료구조 중 하나로, 컴퓨터 프로그램을 작성할 때 자주 이용되는 개념이다. 스택은 자료를 넣는 (push) 입구와 자료를 뽑는 (pop) 입구가 같아 제일 나중에 들어간 자료가 제일 먼저 나오는 (LIFO, Last in First out) 특성을 가지고 있다.

1부터 n까지의 수를 스택에 넣었다가 뽑아 늘어놓음으로써, 하나의 수열을 만들 수 있다. 이때, 스택에 push하는 순서는 반드시 오름차순을 지키도록 한다고 하자. 임의의 수열이 주어졌을 때 스택을 이용해 그 수열을 만들 수 있는지 없는지, 있다면 어떤 순서로 push와 pop 연산을 수행해야 하는지를 알아낼 수 있다. 이를 계산하는 프로그램을 작성하라.

 

입력


첫 줄에 n (1 ≤ n ≤ 100,000)이 주어진다. 둘째 줄부터 n개의 줄에는 수열을 이루는 1이상 n이하의 정수가 하나씩 순서대로 주어진다. 물론 같은 정수가 두 번 나오는 일은 없다.

 

출력


입력된 수열을 만들기 위해 필요한 연산을 한 줄에 한 개씩 출력한다. push연산은 +로, pop 연산은 -로 표현하도록 한다. 불가능한 경우 NO를 출력한다.

 

예제 입력과 출력

 

 

알고리즘 분류


스택

 

정답

 

from collections import deque
import sys
input = lambda : sys.stdin.readline().strip()

def push(i):
    s.append(i)
    li.append('+')
    
def popp():
    li.append('-')
    s.pop()

n=int(input())
a=[int(input()) for i in range(n)]
s=deque()
li=deque()
p='Y'
for i in range(1,a[0]+1):
    push(i)

m=max(s)
popp()

for i in range(1,n):
    if a[i] < a[i-1]:
        if s[-1] == a[i]:
            popp()
        else:
            p='NO'
            break
        
    elif a[i] > a[i-1]:
        for j in range(m+1,a[i]+1):
            push(j)

        m=max(s)
        popp()

if p == 'NO':
    print(p)
else:
    for i in li:
        print(i)

1. 첫번째 수까지 push하고 pop을 합니다.
2. 두번째부터 n번째까지 스택을 이용해 수열을 만들 수 있는지 확인합니다.
3. 리스트의 앞자리와 뒷자리의 수를 비교합니다.
3-1. 앞자리가 더 큰 경우 스택의 마지막 값과 뒷자리의 수가 같으면 pop을 합니다.
3-2. 뒷자리가 더 큰 경우 스택에 해당 수까지 push 합니다.
4. 각 단계마다 리스트 li에 push에는 '+'를, pop에는 '-'를 추가하여 출력합니다.

 


백준 알고리즘 1874번 : https://www.acmicpc.net/problem/1874

 

1874번: 스택 수열

1부터 n까지에 수에 대해 차례로 [push, push, push, push, pop, pop, push, push, pop, push, push, pop, pop, pop, pop, pop] 연산을 수행하면 수열 [4, 3, 6, 8, 7, 5, 2, 1]을 얻을 수 있다.

www.acmicpc.net

 

문제


여러 개의 쇠막대기를 레이저로 절단하려고 한다. 효율적인 작업을 위해서 쇠막대기를 아래에서 위로 겹쳐 놓고, 레이저를 위에서 수직으로 발사하여 쇠막대기들을 자른다. 쇠막대기와 레이저의 배치는 다음 조건을 만족한다.

  • 쇠막대기는 자신보다 긴 쇠막대기 위에만 놓일 수 있다. - 쇠막대기를 다른 쇠막대기 위에 놓는 경우 완전히 포함되도록 놓되, 끝점은 겹치지 않도록 놓는다.
  • 각 쇠막대기를 자르는 레이저는 적어도 하나 존재한다.
  • 레이저는 어떤 쇠막대기의 양 끝점과도 겹치지 않는다.

아래 그림은 위 조건을 만족하는 예를 보여준다. 수평으로 그려진 굵은 실선은 쇠막대기이고, 점은 레이저의 위치, 수직으로 그려진 점선 화살표는 레이저의 발사 방향이다.

이러한 레이저와 쇠막대기의 배치는 다음과 같이 괄호를 이용하여 왼쪽부터 순서대로 표현할 수 있다.

  1. 레이저는 여는 괄호와 닫는 괄호의 인접한 쌍 ‘( ) ’ 으로 표현된다. 또한, 모든 ‘( ) ’는 반드시 레이저를 표현한다.
  2. 쇠막대기의 왼쪽 끝은 여는 괄호 ‘ ( ’ 로, 오른쪽 끝은 닫힌 괄호 ‘) ’ 로 표현된다.

위 예의 괄호 표현은 그림 위에 주어져 있다.

쇠막대기는 레이저에 의해 몇 개의 조각으로 잘려지는데, 위 예에서 가장 위에 있는 두 개의 쇠막대기는 각각 3개와 2개의 조각으로 잘려지고, 이와 같은 방식으로 주어진 쇠막대기들은 총 17개의 조각으로 잘려진다.

쇠막대기와 레이저의 배치를 나타내는 괄호 표현이 주어졌을 때, 잘려진 쇠막대기 조각의 총 개수를 구하는 프로그램을 작성하시오.

 

입력

 

한 줄에 쇠막대기와 레이저의 배치를 나타내는 괄호 표현이 공백없이 주어진다. 괄호 문자의 개수는 최대 100,000이다. 

출력


잘려진 조각의 총 개수를 나타내는 정수를 한 줄에 출력한다.

 

예제 입력과 출력

 

 

알고리즘 분류


스택

 

정답

 

a=list(input())
s=[]
b=0

for i in range(len(a)):
    if a[i] == '(':
        s.append('(')
        
    else:
        if a[i-1] == '(':
            s.pop()
            b=b+len(s)
        
        else:
            s.pop()
            b=b+1

print(b)

(이 나오면 스택에 넣습니다.

()이 나오면 현재 스택에 있는 ( 수만큼 정답에 더해줍니다.

)이 나오면 스택의 (를 pop하고 정답에 1을 더해줍니다.

 


백준 알고리즘 10799번 : www.acmicpc.net/problem/10799

 

10799번: 쇠막대기

여러 개의 쇠막대기를 레이저로 절단하려고 한다. 효율적인 작업을 위해서 쇠막대기를 아래에서 위로 겹쳐 놓고, 레이저를 위에서 수직으로 발사하여 쇠막대기들을 자른다. 쇠막대기와 레이저�

www.acmicpc.net

 

문제


괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’ 와 ‘)’ 만으로 구성되어 있는 문자열이다. 그 중에서 괄호의 모양이 바르게 구성된 문자열을 올바른 괄호 문자열(Valid PS, VPS)이라고 부른다. 한 쌍의 괄호 기호로 된 “( )” 문자열은 기본 VPS 이라고 부른다. 만일 x 가 VPS 라면 이것을 하나의 괄호에 넣은 새로운 문자열 “(x)”도 VPS 가 된다. 그리고 두 VPS x 와 y를 접합(concatenation)시킨 새로운 문자열 xy도 VPS 가 된다. 예를 들어 “(())()”와 “((()))” 는 VPS 이지만 “(()(”, “(())()))” , 그리고 “(()” 는 모두 VPS 가 아닌 문자열이다.

여러분은 입력으로 주어진 괄호 문자열이 VPS 인지 아닌지를 판단해서 그 결과를 YES 와 NO 로 나타내어야 한다.

 

입력


입력 데이터는 표준 입력을 사용한다. 입력은 T개의 테스트 데이터로 주어진다. 입력의 첫 번째 줄에는 입력 데이터의 수를 나타내는 정수 T가 주어진다. 각 테스트 데이터의 첫째 줄에는 괄호 문자열이 한 줄에 주어진다. 하나의 괄호 문자열의 길이는 2 이상 50 이하이다. 

 

출력


출력은 표준 출력을 사용한다. 만일 입력 괄호 문자열이 올바른 괄호 문자열(VPS)이면 “YES”, 아니면 “NO”를 한 줄에 하나씩 차례대로 출력해야 한다. 

 

예제 입력과 출력

 

 

알고리즘 분류


스택

 

정답

 

t=int(input())
b=list()

for i in range(t):
    a=input()
    b.clear()

    if len(a) % 2 == 1:
        print('NO')
        continue

    for j in range(len(a)):
        if a[j] == '(':
            b.append('(')
            
        elif a[j] == ')':
            if j== len(a)-1 and len(b)==1:
                print('YES')
                
            if len(b) == 0:
                print('NO')
                break

            if b[-1] == '(':
                b.pop()
            else:
                print('NO')

    if len(b) != 0:
        print('NO')

 


백준 알고리즘 9012번 : www.acmicpc.net/problem/9012

 

9012번: 괄호

문제 괄호 문자열(Parenthesis String, PS)은 두 개의 괄호 기호인 ‘(’ 와 ‘)’ 만으로 구성되어 있는 문자열이다. 그 중에서 괄호의 모양이 바르게 구성된 문자열을 올바른 괄호 문자열(Valid PS, VPS)��

www.acmicpc.net

 

문제


정수를 저장하는 스택을 구현한 다음, 입력으로 주어지는 명령을 처리하는 프로그램을 작성하시오.

명령은 총 다섯 가지이다.

  • push X: 정수 X를 스택에 넣는 연산이다.
  • pop: 스택에서 가장 위에 있는 정수를 빼고, 그 수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.
  • size: 스택에 들어있는 정수의 개수를 출력한다.
  • empty: 스택이 비어있으면 1, 아니면 0을 출력한다.
  • top: 스택의 가장 위에 있는 정수를 출력한다. 만약 스택에 들어있는 정수가 없는 경우에는 -1을 출력한다.

 

입력


첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 않은 명령이 주어지는 경우는 없다.

 

출력


출력해야하는 명령이 주어질 때마다, 한 줄에 하나씩 출력한다.

 

예제 입력과 출력

 

 

알고리즘 분류


스택

 

정답

 

import sys

def push(c):
    b.append(c)

def pop():
    if len(b) == 0:
        print(-1)
    else:
        print(b.pop())

def size():
    print(len(b))

def empty():
    if len(b) == 0:
        print(1)
    else:
        print(0)
        
def top():
    if len(b) == 0:
        print(-1)
    else:
        print(b[-1])

n=int(input())
b=[]
    
for i in range(n):
    c=sys.stdin.readline().strip()
    a=c.split(' ')

    if a[0] == 'push':
        push(a[1])
    elif a[0] == 'pop':
        pop()
    elif a[0] == 'size':
        size()
    elif a[0] == 'empty':
        empty()
    elif a[0] == 'top':
        top()

 


백준 알고리즘 10828번 : www.acmicpc.net/problem/10828

 

10828번: 스택

첫째 줄에 주어지는 명령의 수 N (1 ≤ N ≤ 10,000)이 주어진다. 둘째 줄부터 N개의 줄에는 명령이 하나씩 주어진다. 주어지는 정수는 1보다 크거나 같고, 100,000보다 작거나 같다. 문제에 나와있지 �

www.acmicpc.net

 

+ Recent posts