기술 블로그

16637번 괄호 추가하기 본문

알고리즘 문제/BOJ

16637번 괄호 추가하기

parkit 2020. 1. 6. 22:16
728x90
반응형

https://www.acmicpc.net/problem/16637



작년인가 풀려고 시도하였다가 시작도 거의 못 한 나에게는 어려운 문제였다.



그러다가 잠깐 시간이 남아서 풀었는데 신기하게도 풀렸다.


처음 풀 당시에는 길이 제한도 19밖에 안 됐었지만, 나올 수 있는 모든 경우의 수가 너무 많고, 무식한 방법인 것 같아서


시도조차 안 했다.


하지만, 길이가 19인 식을 직접 A4에 써보면서 나올 수 있는 모든 괄호의 경우의 수를 생각하고 써보니


별로 많지 않았다.


그래서 나올 수 있는 모든 경우의 수를 백트래킹 함수를 통해 구현하였다.



더 말하자면,


1+2+3+4+9*1+9


일 때,


각 연산자의 문자열 인덱스 번호는 1, 3, 5, 7, 9, 11임을 알 수 있다.


그래서 첨부한 코드 기준 66번 째 줄을 보면 이런 식으로 구현되어 있다.



참고로 23 ~ 27번 째 줄을 구현한 이유는


1+2+3..을 보자면


괄호는


(1+2)+3 이거나 1+(2+3)이다.


(1+(2)+3) 이런 식으로 묶을 수 없다.


즉, 연산자에 대한 문자열 인덱스의 번호는 서로 차이가 4이상이 되어야 한다.







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
#include <bits/stdc++.h>
 
using namespace std;
 
#define Max 20
 
int n, ans = INT32_MIN, temp[Max];
string s;
bool use[Max];
 
int calc(int a, int b, char c)
{
    if (c == '+'return a + b;
    if (c == '-'return a - b;
    if (c == '*'return a * b;
}
 
void bt(vector<int> vc, int idx)
{
    if (!vc.empty()) {
 
        // 차이가 2차이 나는 것은 안 된다.
        for (int i = 0; i < vc.size() - 1; i++) {
            if (vc[i + 1- vc[i] == 2) {
                return;
            }
        }
 
        memset(use, falsesizeof(use));
 
        for (auto i : vc) {
            if (i == 1) {
                // 어차피 첫 번째 연산자는 괄호가 필요 없다.
                continue;
            }
            use[i] = true;
 
            // 미리 괄호 안에 있는 수식의 결과를 temp 배열에 저장한다.
            temp[i] = calc(s[i - 1- '0', s[i + 1- '0', s[i]);
        }
 
        // 첫 숫자
        int number = s[0- '0';
 
        for (int i = 1; i < n - 1; i += 2) {
            if (i + 2 < n && use[i + 2]) {
                // i + 2가 범위를 벗어나지 않고, s[i + 2](=연산자)가 괄호 안에 있는 연산자라면 계산
                // 1*2+3이고 1*(2+3)을 계산한다고 하자.
                // 그렇다면 *(i=1)를 계산할 때 +(i+2)가 괄호 안에 있는 연산자라면 
                // 미리 계산된 결과(temp[i + 2])를 불러와야한다.
                number = calc(number, temp[i + 2], s[i]);
            }
            else {
                if (use[i]) {
                    // 괄호 안에 있는 연산자라면 아래의 식을 수행할 필요가 없다.
                    continue;
                }
                number = calc(number, s[i + 1- '0', s[i]);
            }
        }
 
        ans = max(ans, number);
    }
 
    // 나올 수 있는 모든 괄호의 수(연산자가 기준이다.)
    for (int i = idx; i < n - 1; i += 2) {
        vc.push_back(i);
        bt(vc, i + 2);
        vc.pop_back();
    }
}
 
int main()
{
    cin.tie(0);
 
    cin >> n >> s;
 
    vector<int> v;
    bt(v, 1);
 
    if (n == 1cout << s << "\n";
    else printf("%d\n", ans);
 
    return 0;
}
cs














728x90
반응형

'알고리즘 문제 > BOJ' 카테고리의 다른 글

10166번 관중석  (0) 2020.01.08
10164번 격자상의 경로  (0) 2020.01.07
괄호 추가하기 시리즈  (0) 2020.01.06
2638번 치즈  (0) 2020.01.06
10217번 KCM Travel  (0) 2020.01.05