백준 2504 - 괄호의 값
2 minute read
문제링크
문제설명
- ’(‘ , ‘)’ , ‘[’ , ‘]’ 로 이루어진 괄호 문자열이 주어진다.
- ’()’ 괄호열은 값이 2이고, ‘[]’ 괄호열은 값이 3이다.
- 모든 괄호가 올바르게 열리고 닫혔다면 올바른 괄호열이 되고, 값을 계산할 수 있다.
- 괄호 안에 괄호가 있는 경우 곱하기, 완성된 괄호끼리는 더하기 연산을 진행한다.
- 예를 들어, (()[[]])([]) 의 경우 2x(2+3x3) + (2x3) = 28 이다.
- 주어진 괄호열이 올바른 괄호열이면 수식이 결과값을 출력하고, 올바르지 않은 괄호열이면 0을 출력하라.
문제접근
- 계산에 우선순위가 존재하기 때문에 앞에서부터 무작정 계산할 수 없고, 중간에 계산된 결과값이 다시 수식에 적용되어야 하기 때문에 재귀호출을 통한 접근을 생각했었다.
- 하지만, 일관된 계산로직을 찾아내기 어려웠고, 괄호열에서 흔히 사용되는 스택 자료구조로 접근을 해보았다.
- 앞에서부터 미리미리 계산이 될 수 있도록 괄호가 적용된 수식을 분배법칙을 통해 풀어냈다.
- 2x(2+3x3)+(2x3) = 2x2 + 2x3x3 + 2x3
- 이제 순차적으로 접근하며 오른쪽 괄호가 등장했을 때마다 결과를 계산해주면 된다.
- 오른쪽 괄호가 들어오면 매칭되는 괄호의 값을 변수 tmp 에 곱해두고 스택을 pop 해준다.
- 오른쪽 괄호 다음에 들어오는 괄호가 왼쪽 괄호라면 두 괄호열의 연산은 덧셈관계로 바뀌어야 한다. 따라서, 곱해진 값들을 모두 더해주고 다음으로 넘어가야하는데 이때, 스택에 남아있는 괄호가 있다면 먼저 모조리 곱해주고 더해주어야 한다.
구현
#include <iostream>
#include <vector>
#include <string>
#include <stack>
using namespace std;
bool checkValidString(string str) {
stack<char> s;
for (int i = 0; i < str.length(); i++) {
if (str[i] == '(' || str[i] == '[') s.push(str[i]);
else {
if (s.size() == 0) return false;
if (str[i] == ')' && s.top() != '(') return false;
else if (str[i] == ']' && s.top() != '[') return false;
else {
s.pop();
}
}
}
if (s.size() != 0) return false;
return true;
}
// 제거되지 못한 괄호 값을 곱해준다.
int remainStackValue(stack<char> s) {
int ret = 1;
while (!s.empty()) {
if (s.top() == '(') ret *= 2;
else if (s.top() == '[') ret *= 3;
s.pop();
}
return ret;
}
// 분배법칙이 적용된 계산 로직
int getValue(string str) {
stack<char> s;
int ans = 0;
int tmp = 1;
for (int i = 0; i < str.length(); i++) {
if (str[i] == '(' || str[i] == '[') s.push(str[i]);
else if (str[i] == ')' || str[i]==']') {
if (str[i] == ')') tmp *= 2;
else if (str[i] == ']') tmp *= 3;
s.pop();
if (i + 1 < str.length()) {
// 오른쪽 괄호 다음이 왼쪽 괄호인 경우 값을 더한다.
if (str[i + 1] == '(' || str[i + 1] == '[') {
tmp *= remainStackValue(s);
ans += tmp;
tmp = 1;
}
}
}
}
ans += tmp;
return ans;
}
int main()
{
cin.tie(NULL);
ios_base::sync_with_stdio(false);
string str;
cin >> str;
// 올바른 문자열인지 확인
bool flag = checkValidString(str);
if (flag == 0) {
printf("0\n");
return 0;
}
int ans = getValue(str);
printf("%d\n", ans);
return 0;
}
Leave a comment