2024. 2. 27. 14:50ㆍC# 백준 알고리즘
괄호의 값
1 초 | 128 MB | 60475 | 16638 | 12541 | 30.293% |
문제
4개의 기호 ‘(’, ‘)’, ‘[’, ‘]’를 이용해서 만들어지는 괄호열 중에서 올바른 괄호열이란 다음과 같이 정의된다.
- 한 쌍의 괄호로만 이루어진 ‘()’와 ‘[]’는 올바른 괄호열이다.
- 만일 X가 올바른 괄호열이면 ‘(X)’이나 ‘[X]’도 모두 올바른 괄호열이 된다.
- X와 Y 모두 올바른 괄호열이라면 이들을 결합한 XY도 올바른 괄호열이 된다.
예를 들어 ‘(()[[]])’나 ‘(())[][]’ 는 올바른 괄호열이지만 ‘([)]’ 나 ‘(()()[]’ 은 모두 올바른 괄호열이 아니다. 우리는 어떤 올바른 괄호열 X에 대하여 그 괄호열의 값(괄호값)을 아래와 같이 정의하고 값(X)로 표시한다.
- ‘()’ 인 괄호열의 값은 2이다.
- ‘[]’ 인 괄호열의 값은 3이다.
- ‘(X)’ 의 괄호값은 2×값(X) 으로 계산된다.
- ‘[X]’ 의 괄호값은 3×값(X) 으로 계산된다.
- 올바른 괄호열 X와 Y가 결합된 XY의 괄호값은 값(XY)= 값(X)+값(Y) 로 계산된다.
예를 들어 ‘(()[[]])([])’ 의 괄호값을 구해보자. ‘()[[]]’ 의 괄호값이 2 + 3×3=11 이므로 ‘(()[[]])’의 괄호값은 2×11=22 이다. 그리고 ‘([])’의 값은 2×3=6 이므로 전체 괄호열의 값은 22 + 6 = 28 이다.
여러분이 풀어야 할 문제는 주어진 괄호열을 읽고 그 괄호값을 앞에서 정의한대로 계산하여 출력하는 것이다.
입력
첫째 줄에 괄호열을 나타내는 문자열(스트링)이 주어진다. 단 그 길이는 1 이상, 30 이하이다.
출력
첫째 줄에 그 괄호열의 값을 나타내는 정수를 출력한다. 만일 입력이 올바르지 못한 괄호열이면 반드시 0을 출력해야 한다.
예제 입력 1
(()[[]])([])
예제 출력 1
28
예제 입력 2
[][]((])
예제 출력 2
0
나의 실력을 깨달은 문제
이 문제는 스택을 이용하여 푸는 문제인데 이 문제가 어떤 답을 원하는지는 바로 알았으나 어떻게 로직을 구현할지 엄청 애먹은 문제였다.
그래서 어떻게 풀어야할지 1시간 정도 고민을 해도 어떻게 짜야할지 모르겠어서 푼 사람들이 로직을 어떻게 설계했는지만 보고 그걸 이용해서 풀었다.
코드가 엄청 더러워지고 길어져서 풀어도 찜찜함 느낌이 들고 그리고 이렇게 풀어도 바로 바로 풀린게 아니라 결국 반례를 찾아달란 질문을 하게되고 그 반례를 보고 거의 하루가 지나고 5시간만에 푼거같다.. 실버 4문제지만 역시 기본기가 부족한 나한테 엄청 애먹은 문제였고 왜 정답자가 30퍼밖에 안되는지도 알게되었다.
ps. 실버 4문제가 아니라 골드 5문제였다. 역시 어려운 이유가 있었다..
이걸 풀고 다른분의 C#코드를 봤는데 엄청 깔끔하게 짠걸 보고 진짜 아직 배워야할게 많구나 깨달았다..
내가 푼 코드
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Prob2504_괄호의_값
{
class Program
{
static int sum;
static void Main(string[] args)
{
string parenthesis = Console.ReadLine();
int index = 0;
Stack<string> stack = new Stack<string>();
while (true)
{
string current = parenthesis[index].ToString();
if (current == ")")
{
if (stack.Count == 0)
{
Console.WriteLine(0);
return;
}
if (stack.Count == 1 && stack.Peek() != "(")
{
Console.WriteLine(0);
return;
}
if (stack.Peek() == "(")
{
int number = 2;
stack.Pop();
while (stack.Count != 0)
{
if (stack.Peek() == "[" || stack.Peek() == "(")
{
stack.Push(number.ToString());
number = 0;
break;
}
else
{
int a = int.Parse(stack.Pop());
number += a;
}
}
if (number != 0)
{
stack.Push(number.ToString());
}
}
else if (stack.Peek() != "(")
{
int number = 0;
while (stack.Count != 0)
{
if (stack.Peek() == "[")
{
Console.WriteLine(0);
return;
}
else if (stack.Peek() == "(")
{
stack.Pop();
number *= 2;
stack.Push(number.ToString());
break;
}
else
{
int a = int.Parse(stack.Pop());
number += a;
}
}
}
}
else if (current == "]")
{
if (stack.Count == 0)
{
Console.WriteLine(0);
return;
}
if (stack.Count == 1 && stack.Peek() != "[")
{
Console.WriteLine(0);
return;
}
if (stack.Peek() == "[")
{
int number = 3;
stack.Pop();
while (stack.Count != 0)
{
if (stack.Peek() == "[" || stack.Peek() == "(")
{
stack.Push(number.ToString());
number = 0;
break;
}
else
{
int a = int.Parse(stack.Pop());
number += a;
}
}
if (number != 0)
{
stack.Push(number.ToString());
}
}
else if (stack.Peek() != "[")
{
int number = 0;
while (stack.Count != 0)
{
if (stack.Peek() == "(")
{
Console.WriteLine(0);
return;
}
else if (stack.Peek() == "[")
{
stack.Pop();
number *= 3;
stack.Push(number.ToString());
break;
}
else
{
int a = int.Parse(stack.Pop());
number += a;
}
}
}
}
else
{
stack.Push(parenthesis[index].ToString());
}
if (stack.Count != 0)
{
if (stack.Peek() == ")" || stack.Peek() == "]")
{
Console.WriteLine(0);
return;
}
}
index++;
if(index == parenthesis.Length)
{
while (stack.Count != 0)
{
if(stack.Peek() == "(" ||
stack.Peek() == "[" ||
stack.Peek() == "]" ||
stack.Peek() == ")")
{
Console.WriteLine(0);
return;
}
sum += int.Parse(stack.Pop());
}
Console.WriteLine(sum);
return;
}
}
}
}
}
'C# 백준 알고리즘' 카테고리의 다른 글
C# 백준 1916 최소비용 구하기 (0) | 2024.03.12 |
---|---|
C# 백준 14719 빗물 (0) | 2024.02.29 |
C# 백준 1010 다리놓기 (0) | 2024.02.25 |
C# 백준 14888 연산자 끼워넣기 (1) | 2024.02.24 |
C# 백준 2581 소수 (1) | 2024.02.24 |