설명
4개의 기호 ‘(’, ‘)’, ‘[’, ‘]’를 이용해서 만들어지는 괄호열 중에서 올바른 괄호열이란 다음과 같이 정의된다.
예를 들어 ‘(()[[]])’나 ‘(())[][]’ 는 올바른 괄호열이지만 ‘([)]’ 나 ‘(()()[]’ 은 모두 올바른 괄호열이 아니다. 우리는 어떤 올바른 괄호열 X에 대하여 그 괄호열의 값(괄호값)을 아래와 같이 정의하고 값(X)로 표시한다.
예를 들어 ‘(()[[]])([])’ 의 괄호값을 구해보자. ‘()[[]]’ 의 괄호값이 2 + 3×3=11 이므로 ‘(()[[]])’의 괄호값은 2×11=22 이다. 그리고 ‘([])’의 값은 2×3=6 이므로 전체 괄호열의 값은 22 + 6 = 28 이다.
여러분이 풀어야 할 문제는 주어진 괄호열을 읽고 그 괄호값을 앞에서 정의한대로 계산하여 출력하는 것이다.
입력
첫째 줄에 괄호열을 나타내는 문자열(스트링)이 주어진다. 단 그 길이는 1 이상, 30 이하이다.
출력
첫째 줄에 그 괄호열의 값을 나타내는 정수를 출력한다. 만일 입력이 올바르지 못한 괄호열이면 반드시 0을 출력해야 한다.
스택을 이용하는 꽤 구현력이 높았던 문제입니다.
저는 스택에 문자열 뿐만 아니라 중간에 계산된 결과값을 같이 저장하면서 풀이했습니다.
문제에서 요구하는 수식에 의해 규칙을 정의하면 다음과 같습니다.
top에 열린 괄호가 있을 때, 알맞는 괄호열 값을 넣어줍니다.['(' -> [2top 바로 뒤에 숫자가 있다면 그 숫자를 더해서 넣어줍니다.[2, '(' -> [2, 2 -> [4top에 숫자가 있을 때, 알맞은 괄호열 값과 숫자를 곱해서 넣어줍니다.['(', 3 -> [6top 바로 뒤에 숫자가 있다면 그 숫자를 더해서 넣어줍니다.[6, '(', 3 -> [12ex)는 왼쪽으로 넣는 stack이라 생각하고 봐주세요.
최종적으로 남은 스택의 값이 우리가 찾는 정답이 됩니다.
#include <iostream>
#include <stack>
#include <string>
using namespace std;
int main(void) {
ios::sync_with_stdio(0);
cin.tie(0);
string s;
cin >> s;
stack<pair<pair<char, int>, bool>> st;
bool flag = true;
// 올바른 괄호열인지 먼저 검사
for (char c : s) {
if (c == '(' || c == '[') st.push(make_pair(make_pair(c, 0), 0));
else if (c == ')') {
if ((st.empty() || st.top().first.first != '(')) {
flag = false;
break;
}
st.pop();
}
else if (c == ']') {
if (st.empty() || st.top().first.first != '[') {
flag = false;
break;
}
st.pop();
}
}
// 올바르지 않을 때
if (!st.empty() || !flag) {
cout << 0;
return 0;
}
// stack clear
while (!st.empty()) st.pop();
for (char c : s) {
if (c == '(' || c == '[') st.push(make_pair(make_pair(c, 0), 0));
else {
int unit = c == ')' ? 2 : 3; // 단위 조절
// 숫자일 때
if (st.top().second) {
// 스택의 top에 숫자가 있을 때, 알맞은 괄호열 값과 숫자를 곱해서 넣어줍니다
int tmp = st.top().first.second * unit;
st.pop();
st.pop();
// top 바로 뒤에 숫자가 있다면 그 숫자를 더해서 넣어줍니다.
if (!st.empty() && st.top().second) {
tmp += st.top().first.second;
st.pop();
}
st.push(make_pair(make_pair(tmp, tmp), 1));
}
// 문자일 때
else {
st.pop();
// top 바로 뒤에 숫자가 있다면 그 숫자를 더해서 넣어줍니다.
if (!st.empty() && st.top().second) {
int tmp = st.top().first.second + unit;
st.pop();
st.push(make_pair(make_pair(tmp, tmp), 1));
}
// 없다면 알맞은 괄호열 값 그대로 넣어줍니다.
else {
st.push(make_pair(make_pair(unit, unit), 1));
}
}
}
}
// 최종적으로 남은 값이 정답이 됩니다.
cout << st.top().first.second;
return 0;
}