Post

[BOJ 2504] 괄호의 값

- 문제풀이

[BOJ 2504] 괄호의 값

문제 링크 : https://www.acmicpc.net/problem/2504

문제

4개의 기호 ‘(’, ‘)’, ‘[’, ‘]’를 이용해서 만들어지는 괄호열 중에서 올바른 괄호열이란 다음과 같이 정의된다.

  1. 한 쌍의 괄호로만 이루어진 ‘()’와 ‘[]’는 올바른 괄호열이다.
  2. 만일 X가 올바른 괄호열이면 ‘(X)’이나 ‘[X]’도 모두 올바른 괄호열이 된다.
  3. XY 모두 올바른 괄호열이라면 이들을 결합한 XY도 올바른 괄호열이 된다.

예를 들어 ‘(()[[]])’나 ‘(())[][]’ 는 올바른 괄호열이지만 ‘([)]’ 나 ‘(()()[]’ 은 모두 올바른 괄호열이 아니다. 우리는 어떤 올바른 괄호열 X에 대하여 그 괄호열의 값(괄호값)을 아래와 같이 정의하고 값(X)로 표시한다.

  1. ()’ 인 괄호열의 값은 2이다.
  2. []’ 인 괄호열의 값은 3이다.
  3. (X)’ 의 괄호값은 2×값(X) 으로 계산된다.
  4. [X]’ 의 괄호값은 3×값(X) 으로 계산된다.
  5. 올바른 괄호열 XY가 결합된 XY의 괄호값은 값(XY)= 값(X)+값(Y) 로 계산된다.

예를 들어 ‘(()[[]])([])’ 의 괄호값을 구해보자. ‘()[[]]’ 의 괄호값이 2 + 3×3=11 이므로 ‘(()[[]])’의 괄호값은 2×11=22 이다. 그리고 ‘([])’의 값은 2×3=6 이므로 전체 괄호열의 값은 22 + 6 = 28 이다.

여러분이 풀어야 할 문제는 주어진 괄호열을 읽고 그 괄호값을 앞에서 정의한대로 계산하여 출력하는 것이다.

입력

첫째 줄에 괄호열을 나타내는 문자열(스트링)이 주어진다. 단 그 길이는 1 이상, 30 이하이다.

출력

첫째 줄에 그 괄호열의 값을 나타내는 정수를 출력한다. 만일 입력이 올바르지 못한 괄호열이면 반드시 0을 출력해야 한다.

제한

시간 제한메모리 제한
1sec128MB

풀이

주어진 괄호열의 규칙에 따라 값을 계산하는 문제다. 괄호가 중첩되는 구조((X))와 나열되는 구조(XY)가 혼합되어 있으므로, 현재의 깊이와 중간 계산 값을 관리하기 위해 스택 자료구조를 활용하는 것이 효과적이다.

문제 해결의 핵심은 각 괄호가 닫힐 때, 해당 깊이에서 계산된 값을 상위 단계로 어떻게 전달하느냐에 있다. 제공된 소스 코드에서는 두 종류의 스택 역할을 하는 배열을 사용한다. 하나는 괄호의 짝을 맞추기 위한 문자형 스택이고, 다른 하나는 각 깊이(인덱스)에서의 합계를 저장하는 정수형 스택(int_stack)이다.

작동 원리는 다음과 같다.

  1. 여는 괄호((, [): 스택에 해당 문자를 추가하여 깊이를 한 단계 높인다.
  2. 닫는 괄호(), ]):
    • 스택이 비어있거나 짝이 맞지 않으면 올바르지 않은 괄호열이므로 $0$을 출력한다.
    • 직전 단계(더 깊은 단계)에서 계산된 값(int_stack[toc + 1])이 있는지 확인한다.
    • 값이 $0$이라면 ()[]와 같은 기본 쌍이므로 해당 값($2$ 또는 $3$)을 현재 단계에 더한다.
    • 값이 존재한다면 중첩된 구조이므로 해당 값에 가중치($2$ 또는 $3$)를 곱하여 현재 단계에 더하고, 하위 단계의 값은 초기화한다.
  3. 최종 계산: 모든 문자열을 처리한 후 스택이 비어있지 않다면 잘못된 형식이므로 $0$을 출력하고, 올바르다면 누적된 최상위 단계의 합계를 출력한다.

입력 문자열의 길이는 $L$이라 할 때 다음과 같은 범위를 가진다.

\[1 \leq L \leq 30\]

길이가 매우 짧기 때문에 스택을 이용한 $O(L)$ 탐색으로 충분히 제한 시간 내에 해결이 가능하다. 중첩된 계산 방식 덕분에 분배 법칙을 적용한 것과 같은 효과를 내며 복잡한 괄호의 값을 정확히 도출할 수 있다.

소스코드

Github Link : Source Code

참고 알고리즘 : 스택

This post is licensed under CC BY 4.0 by the author.