Language Grammar/C++
2024 - 08- 05 C++ 코딩테스트 10주완성 D+26
Jang_^
2024. 8. 5. 18:28
백준 4949 문제 : 균형잡힌 세상
대괄호 "[ ]" 와 소괄호 "( )" 가 있다.
- 모든 왼쪽 소괄호("(")는 오른쪽 소괄호(")")와만 짝을 이뤄야 한다.
- 모든 왼쪽 대괄호("[")는 오른쪽 대괄호("]")와만 짝을 이뤄야 한다.
- 모든 오른쪽 괄호들은 자신과 짝을 이룰 수 있는 왼쪽 괄호가 존재한다.
- 모든 괄호들의 짝은 1:1 매칭만 가능하다. 즉, 괄호 하나가 둘 이상의 괄호와 짝지어지지 않는다.
- 짝을 이루는 두 괄호가 있을 때, 그 사이에 있는 문자열도 균형이 잡혀야 한다.
이 조건을 만족하면 "yes" 를 출력
만족하지 못하면 "no" 를 출력한다.
입력
각 문자열은 마지막 글자를 제외하고 영문 알파벳, 공백, 소괄호("( )"), 대괄호("[ ]")로 이루어져 있으며, 온점(".")으로 끝나고, 길이는 100글자보다 작거나 같다.
입력의 종료조건으로 맨 마지막에 온점 하나(".")가 들어온다.
출력
각 줄마다 해당 문자열이 균형을 이루고 있으면 "yes"를, 아니면 "no"를 출력한다.
실습코드
#include <bits/stdc++.h>
using namespace std;
//1. 변수목록
//소괄호의 수를 체크할 스택 sbk
//대괄호의 수를 체크할 스택 lbk
//입력받을 문자열 str
vector<char> m_vector;
char str[104];
bool isflag = true;
void StackList(char a)
{
if (a == '(' || a == ')' || a == '[' || a == ']')
{
m_vector.push_back(a);
}
}
int main()
{
//2.알고리즘
//2-1. 무한루프로 반복문
//2-2. 문자열을 입력받는다. ( 문자열이 . 일시 break)
//2-3. 문자열의 길이만큼 반복문
//2-3-1. ([]) -> ( 스택 -> [ 스택 -> ] push -> 만약 [] 사이즈가 0일경우 isflag true
while (true)
{
cin.getline(str,100,'.');
for (char i : str)
{
StackList(i);
}
vector<char> r_vector;
if (m_vector.size() % 2 != 0)
isflag = false;
else
for (int i = m_vector.size()/2 ; i < m_vector.size(); i++)
{
r_vector.push_back(m_vector.back());
m_vector.pop_back();
}
for (int i = 0; i < r_vector.size(); i++)
{
r_vector.reserve(r_vector.size());
char a;
if (m_vector[i] == '(')
a = ')';
else
a = ']';
if (a != r_vector[i])
isflag = false;
}
if (isflag)
cout << "yes" << endl;
else
cout << "no" << endl;
}
}
처음에는 두개의 스택으로 소괄호 "( )" 와 대괄호 "[ ]" 의 조합마다 Pop Push를 하여주어 출력을 하려고 하였으나,
예를 들어 "( [ ) ] " 라는 한쌍이 생길 경우에는 Yes가 되어버린다...
그래서 생각해낸게 괄호만 받은 Vector를 반으로 잘라 그 두개가 같으면 Yes 아니면 No라고 출력하려고 하였으나..
무조건 반으로 잘라야지만 Yes 인 경우가 나오지는 않았다..
예를 들어 "( [ ] ( ) ) " 인 경우에는
내가 짠 알고리즘으로 진행할 시 " ( [ ] " 와 " ( ) ) " 를 비교하므로 당연히 No가 된다.
하지만 원래 조건대로라면 Yes가 되어야 한다.
모르겠다.. 강의 실습코드를 보자 ㅠ
강의 실습코드
#include <bits/stdc++.h>
using namespace std;
int main() {
while (true) {
string s;
getline(cin, s);
if (s == ".") break;
stack<int> stk;
bool check = true;
for (int i = 0; i < s.length(); i++) {
if (s[i] == ')') {
if (stk.size() == 0 || stk.top() == '[') {
check = false;
break;
}
else {
stk.pop();
}
}
if (s[i] == ']') {
if (stk.size() == 0 || stk.top() == '(') {
check = false;
break;
}
else {
stk.pop();
}
}
if (s[i] == '(') stk.push(s[i]);
if (s[i] == '[') stk.push(s[i]);
}
if (check && stk.size() == 0) cout << "yes\n";
else cout << "no\n";
}
return 0;
}
이 짝짓기 문제에서는 "( ) " 또는 " [ ] " 가 무조건 한쌍으로 합쳐져야 하기 떄문에
괄호의 제일 안에 있는 ' ( ' 또는 ' [ ' 는 같은 유형의 괄호가 나와서 괄호를 닫아 줘야 규칙이 성립이 된다!
그래서 Stack 의 Top은 이전 글자에 해당하기 때문에 비교하여
만약 같은 괄호가 아닐 경우 "no" 를 출력하고
같은 괄호일 경우 "yes"를 출력하면 된다!!
세삼 느끼는 거지만 알고리즘 문제는 간단한 규칙만 생각해서 찾으면 되는데,
그게 제일 어려운 것 같다.....