공부/백준

14888번: 연산자 끼워넣기(백준 C++)

상연 2020. 11. 11. 01:28

목차

    14888번: 연산자 끼워넣기 링크

    코드

    #include <iostream>
    #include <climits>
    using namespace std;
    
    int oper[4] = {0, }; // + - * /
    int num[100];
    
    int n;
    
    int max_num = INT_MIN;
    int min_num = INT_MAX;
    
    void solve(int cnt, int now){
        if(cnt == n){
            max_num = now > max_num ? now : max_num;
            min_num = now < min_num ? now : min_num;
        }
        else{
            for(int j=0; j<4; j++){
                if(oper[j] == 0) continue;
                else{
                    int temp = now;
                    if(j == 0) now += num[cnt];
                    else if(j == 1) now -= num[cnt];
                    else if(j == 2) now *= num[cnt];
                    else if(j == 3) now /= num[cnt];
                    oper[j] -= 1;
                    solve(cnt+1, now);
                    oper[j] += 1;
                    now = temp;
                }
            }
        }
    }
    
    int main() {
        cin >> n;
        for(int i=0; i<n; i++){
            cin >> num[i];
        }
        for(int j=0; j<4; j++){
            cin >> oper[j];
        }
        solve(1, num[0]);
        cout << max_num << endl << min_num;
        return 0;
    }
    

    풀이 및 사견

    단계별 문제풀이에서 백트래킹을 풀 수록 약간 느껴지는게 있다.
    백트래킹류 문제 풀이를 할 때 가장 중요하게 생각해야 하는 것 두 가지.

    1. 재귀 종료 조건
    2. 반복문의 간소화

    나의 이번 문제에 대한 재귀 종료 조건

    if(cnt == n){
            max_num = now > max_num ? now : max_num;
            min_num = now < min_num ? now : min_num;
        }

    cnt는 연산에 사용된 연산자의 개수이다.
    문제에서 N개의 수와 N-1개의 연산자를 사용하여 최대값과 최소값을 구하라 하였으므로
    연산자의 사용 수가 N개째, 즉 주어진 N-1개를 초과하여 사용하기 전에 재귀를 종료하는 것이다.

    나의 이번 문제에 대한 반복

    for(int j=0; j<4; j++){
                if(oper[j] == 0) continue;
                else{
                    int temp = now;
                    if(j == 0) now += num[cnt];
                    else if(j == 1) now -= num[cnt];
                    else if(j == 2) now *= num[cnt];
                    else if(j == 3) now /= num[cnt];
                    oper[j] -= 1;
                    solve(cnt+1, now);
                    oper[j] += 1;
                    now = temp;
                }
            }

    단순히 연산자들만 저장되어 있는 oper 배열에 대해서만 반복문을 돌려주고, 연산자 사용 개수는 재귀함수의 인자로 넘겨서 세었다. 백트래킹 문제 풀때 이중반복문으로 풀면 대개는 시간초과가 나는 듯 하다.

    어제 엊그제 이보다 조금 어려운 난이도를 풀었더니 그래도 생각보다 할 만했다.
    푸는데도 얼마 걸리지 않았고... 백트래킹에 대한 어느정도 감이 잡혀간다.

    '공부 > 백준' 카테고리의 다른 글

    2748번: 피보나치 수2(백준 C++)  (0) 2020.11.13
    14889번: 스타트와 링크(백준 C++)  (0) 2020.11.12
    2580번: 스도쿠(백준 C++)  (0) 2020.11.10
    9663번: N-Queen(백준 C++)  (0) 2020.11.09
    1010번: 다리 놓기(백준 C++)  (0) 2020.11.08