Algorithm/백준

[Java] BaekJoon 2800. 괄호 제거(골드5) (부분집합) (DFS)

Per ardua ad astra ! 2021. 10. 7. 16:55

문제출처: https://www.acmicpc.net/problem/2800

 

2800번: 괄호 제거

첫째 줄에 음이 아닌 정수로 이루어진 수식이 주어진다. 이 수식은 괄호가 올바르게 쳐져있다. 숫자, '+', '*', '-', '/', '(', ')'로만 이루어져 있다. 수식의 길이는 최대 200이고, 괄호 쌍은 적어도 1개

www.acmicpc.net

 

문제이해

 

목표

어떤 수식이 주어졌을 때, 괄호를 제거해서 나올 수 있는 서로 다른 식의 개수를 계산하는 프로그램을 작성하시오. 괄호를 제거할 때는, 항상 쌍이 되는 괄호끼리 제거해야 한다.
ex) 
입력 : (0/(0))
출력:
(0/0)
0/(0)
0/0

 

풀이

 

1. 괄호쌍의 인덱스를 Stack을 이용하여 찾아서 저장한다.

2. 각 괄호쌍의 제거 or 제거안함을 이용하여 부분집합, 2의 n제곱 만큼의 경우의 수를 탐색한다.  

   => 괄호 제거는 visited[] =falase 로 한다.

  각 경우(재귀가 끝이나서 now==count 일때), visited를 체크하여 true인 것만 출력하면

  괄호를 제거하고 잘 출력 할 수 있다.

 

주의 

괄호를 제거할 때 visited로 하지 않고 StringBuilder로 만들어서 한 쌍, 한 쌍을 제거하면 인덱스가 밀려서 정확하게 괄호를 제거할 수 없다. 원본 String을 유지하면서 따로 visited를 만들어서 true인 것만 출력할 수 있도록 하자

 

소스코드

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;

import static java.lang.System.in;

public class 괄호제거 {
    private static HashSet<String> answer;
    private static ArrayList<int[]> pairs;
    private static int count;
    private static boolean[] visited;
    private static char[] charArr;

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String s = br.readLine();
        pairs = new ArrayList<>();
        answer = new HashSet<>();
        visited = new boolean[s.length()];
        Arrays.fill(visited, true);

        // 괄호 쌍의 인덱스를 찾아서 저장
        charArr = s.toCharArray();
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < s.length(); i++) {
            if (charArr[i] == '(') {
                stack.add(i);
            } else if (charArr[i] == ')') {
                pairs.add(new int[]{stack.pop(), i});
            }
        }
        count = pairs.size(); // 부분집합으로 탐색해야한 괄호쌍의 size

        removeGaul(0); // 핵심 알고리즘

        // 정답 도출
        answer.remove(s);
        List<String> answerList = new ArrayList(answer);
        Collections.sort(answerList);
        StringBuilder sb = new StringBuilder();
        for (String s1 : answerList) {
            sb.append(s1).append("\n");
        }
        System.out.println(sb);
    }

    private static void removeGaul(int now) { // 부분집합
        if (now == count) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < visited.length; i++) {
                if (visited[i]) {
                    sb.append(charArr[i]);
                }
            }
            answer.add(sb.toString());
            return;
        }

        // 부분집합
        // 괄호를 제거하지 않고 재귀
        int[] pair = pairs.get(now);
        visited[pair[0]] = true;
        visited[pair[1]] = true;
        removeGaul(now + 1);

        // 괄호를 제거하고 재귀
        visited[pair[0]] = false;
        visited[pair[1]] = false;
        removeGaul(now + 1);
    }
}