https://www.acmicpc.net/problem/2800
처음에는 단순히 왼쪽 괄호가 몇 개 나오는지를 재귀함수의 파라미터로 두는 방향으로 접근했지만 생각대로 잘 풀리지 않았다. 결국 힌트를 살짝 얻었는데, 본인이 생각했던 방향과 가장 큰 차이점은 아래와 같았다.
힌트 : 괄호 짝에 맞는 번호를 사전에 저장해둔다.
본인 : 현재 '('가 몇 개 나왔는지에 대해 파라미터로 두고 매번 비교한다.
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.Stack;
public class Main {
  static String str; // 입력 문자열
  static Set<String> set = new HashSet<>(); // 정답 셋
  static int[] pair; // 괄호 번호를 저장할 배열. 괄호가 아닌 경우 0을 저장
  static boolean[] visited; // 없앨 괄호 집합을 위한 배열. 없앨 괄호 번호라면 true
  public static void main(String[] args) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
    str = br.readLine();
    pair = new int[str.length()];
    int num = 0;
    Stack<Integer> stack = new Stack<>();
    for (int i = 0; i < str.length(); i++) {
      char c = str.charAt(i);
      if (c == '(') {
        pair[i] = ++num;
        stack.push(num);
      } else if (c == ')') {
        pair[i] = stack.pop();
      } else {
        pair[i] = 0;
      }
    }
    visited = new boolean[num + 1];
    func(1);
    List<String> list = new ArrayList<>(set);
    Collections.sort(list);
    for (String ans : list) {
      if (!ans.equals(str)) {
        bw.write(ans + '\n');
      }
    }
    bw.flush();
    bw.close();
    br.close();
  }
  static void func(int idx) {
    if (idx == visited.length) {
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < str.length(); i++) {
        if (!visited[pair[i]]) {
          // 없앨 문자가 아니라면 문자열을 이어붙인다.
          sb.append(str.charAt(i));
        }
      }
      String tmpStr = sb.toString();
      if (set.isEmpty() || !set.contains(tmpStr)) {
        set.add(tmpStr);
      }
      return;
    }
    for (int i = idx; i < visited.length; i++) {
      visited[i] = true;
      func(i + 1);
      visited[i] = false;
      func(i + 1);
    }
  }
}