article thumbnail image
Published 2022. 10. 1. 22:45

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

 

 

 

 

#include <bits/stdc++.h>
using namespace std;
string str;
stack<char> st;
int result, num = 1, valid = 1;

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);

  cin >> str;
  for (int i = 0; i < str.length(); i++) {
    if (str[i] == '(') {
      num *= 2;
      st.push(str[i]);
    } else if (str[i] == '[') {
      num *= 3;
      st.push(str[i]);
    } else if (str[i] == ')') {
      if (st.empty() || st.top() != '(') {
        cout << 0;
        return 0;
      }
      if (str[i - 1] == '(') result += num;
      st.pop();
      num /= 2;
    } else {
      if (st.empty() || st.top() != '[') {
        cout << 0;
        return 0;
      }
      if (str[i - 1] == '[') result += num;
      st.pop();
      num /= 3;
    }
  }
  if (st.empty())
    cout << result << '\n';
  else
    cout << 0 << '\n';
}

괄호의 값을 분배법칙을 이용해서 풀려고 시도했다.

(()[[]])([])

문제의 입력이 위와 같을 때 괄호의 값은 (2 + 3 * 3) * 2 + 2 * 2이 된다.

위 식에 분배법칙을 적용한다면 2 * 2 + 2 * 3 * 3 + 2 * 2가 될 것이다.

 

주어진 입력과 분배법칙을 적용한 식을 비교해보면 2 또는 3이 곱해지는 개수가 열린 괄호의 개수와 비슷하다는 것을 알 수 있다.

좀 더 깊게 생각해보면 스택에 들어 있는 괄호들의 곱이라는 것을 알 수 있다.

즉 스택에 '(', '(' 이 들어 있다면 2 * 2가 되고, '(', '[', '[' 가 들어있다면 2 * 3 * 3이 되는 것이다.

 

코드로 구현하자면 열린 괄호는 무조건 스택에 push하고, 각 괄호가 가지는 값을 num에 곱한다.

=> '(' 는 2, '[' 는 3

 

닫힌 괄호는 스택의 탑과 비교해서 짝이 맞지 않으면 맞는 괄호쌍이 아니므로 0을 출력하고 프로그램을 종료한다.

 

괄호쌍이 맞다면 (), [] 처럼 연속하는 쌍인지 확인하고 참이라면 result에 num을 더해야 한다.

=> 식과 비교해모녀 (), [] 부분이 곱의 마지막이기 때문

 

이후에는 pop 연산과 num의 값을 다시 조정해야 한다.

그 이유는 현재 괄호가 올바른 괄호쌍이기 때문에 pop 연산을 수행해야 한다.

또 pop 연산을 수행하면 괄호 하나가 스택에서 제거되기 때문에 제거된 괄호의 값에 맞게 num을 나눠야 한다.

 

위 과정을 반복해서 반복문이 종료되면 st.empty()로 스택에 비었는지를 판단하고 1이면 result를 0이면 0을 반환한다.

 

 

 

 

 

 

'알고리즘' 카테고리의 다른 글

[BOJ] 11003: 최솟값 찾기  (0) 2022.10.03
[BOJ] 2493: 탑  (0) 2022.10.02
[BOJ] 10799: 쇠막대기  (0) 2022.10.01
[BOJ] 3986: 좋은 단어  (0) 2022.10.01
[BOJ] 5430: AC  (0) 2022.10.01
복사했습니다!