백준 10799번 : 쇠막대기

2yunseong·2022년 5월 19일
1

문제

출처 : https://www.acmicpc.net/problem/10799
여러 개의 쇠막대기를 레이저로 절단하려고 한다. 효율적인 작업을 위해서 쇠막대기를 아래에서 위로 겹쳐 놓고, 레이저를 위에서 수직으로 발사하여 쇠막대기들을 자른다. 쇠막대기와 레이저의 배치는 다음 조건을 만족한다.

쇠막대기는 자신보다 긴 쇠막대기 위에만 놓일 수 있다. - 쇠막대기를 다른 쇠막대기 위에 놓는 경우 완전히 포함되도록 놓되, 끝점은 겹치지 않도록 놓는다.

  • 각 쇠막대기를 자르는 레이저는 적어도 하나 존재한다.
  • 레이저는 어떤 쇠막대기의 양 끝점과도 겹치지 않는다.

이러한 레이저와 쇠막대기의 배치는 다음과 같이 괄호를 이용하여 왼쪽부터 순서대로 표현할 수 있다.

레이저는 여는 괄호와 닫는 괄호의 인접한 쌍 ‘( ) ’ 으로 표현된다. 또한, 모든 ‘( ) ’는 반드시 레이저를 표현한다.
쇠막대기의 왼쪽 끝은 여는 괄호 ‘ ( ’ 로, 오른쪽 끝은 닫힌 괄호 ‘) ’ 로 표현된다.
위 예의 괄호 표현은 그림 위에 주어져 있다.(그림은 위 링크 참고)

쇠막대기는 레이저에 의해 몇 개의 조각으로 잘려지는데, 위 예에서 가장 위에 있는 두 개의 쇠막대기는 각각 3개와 2개의 조각으로 잘려지고, 이와 같은 방식으로 주어진 쇠막대기들은 총 17개의 조각으로 잘려진다.

쇠막대기와 레이저의 배치를 나타내는 괄호 표현이 주어졌을 때, 잘려진 쇠막대기 조각의 총 개수를 구하는 프로그램을 작성하시오

아이디어

먼저, barCount를 측정할 변수를 하나 선언한다.
그리고 다음의 규칙을 따른다.
1. ( 가 나오면 무조건 barCount를 +1 시킨다.
2. ) 가 나오면 다음의 조건을 따른다.

  • 만약 이전의 문자가 ( 였다면, 이는 레이저이다. 따라서, barCount를 1 감소 시킨 값을 answer에 더한다.
  • 만약 이전의 문자가 ) 였다면, 이는 쇠막대기를 닫는 것이다. 따라서, 쇠막대기가 끝난 것이므로 answer에 +1을 하고 barCount 값을 감소 시켜준다.

왜 이렇게 풀까? 먼저 이런 문제는, 이미 결과를 보고 쇠막대기를 자르려고 하면 머리가 아프다. 그러기 때문에, 앞에서부터 차근차근 반복문이 돌 때마다 상태가 어떻게 변하는지 관찰하는게 중요하다고 생각한다.

문제의 예시를 보자.


이 그림을 보면, 레이저가 생길 때, barCount 만큼 잘린 쇠막대기들이 생성됨을 볼 수 있다. 너무 당연한 사실이다.
따라서, 위 조건에 따라, 레이저면 barCount를 1 감소 시키고 barCount 개수를 answer에 더해주어야 한다.( 1을 감소 시켜주는 이유는 레이져를 표현하기 때문)

두 번째 예시를 보자.

이미 이전 괄호가 닫힌 괄호인데 또 닫힌 괄호가 오면 이는 쇠막대기의 종료를 말한다. 그러면 쇠막대기는 무조건 잘려서 나온다. 생각해보면, 1개 이상의 쇠막대기를 표현하기 위해서는 반드시 안에 레이저가 존재한다. 따라서, 잘려나온 쇠막대기 하나가 생성되므로 answer에 +1을 해주고, 쇠막대기 하나가 다 잘렸으므로 barCount 를 1 감소 시켜준다.

내 풀이

간단하다. 입력 로직은 생략하겠다.
prev는 이전의 괄호의 상태를 저장하는 변수이다.

function solve() {
    let barCount = 0;
    let answer = 0;
    let prev = '';
    for(let c of input){
        if( c == '('){
            barCount++;
            prev = '(';
        }
        else if(c == ')'){
            if(prev == '('){
                barCount -= 1;
                answer += barCount;
            }
            else if(prev == ')'){
                answer += 1
                barCount--;
            }
            prev = ')';
        }
    }

    console.log(answer);
}

피드백

시간복잡도는 문자열의 길이가 N이라면, O(N). N이 최대 10만이므로 손쉽게 처리 가능하다.
처음에는 이상하게 생각해서 시간이 오래걸렸다.
밑에 힌트를 보지말자!! 괜히 생각하는 길을 막는 것 같다.

기타

나름 성장한 거 같은 느낌^_^

profile
개발 발자국 남기기

0개의 댓글