[백준] 14888. 연산자 끼워넣기

랑발자🐅·2025년 12월 12일
post-thumbnail

요즘 코딩테스트 속성 준비 강의를 듣고 있다.
(https://skillflo.io/course/10459?productId=18173&tab=info
이 강의 part5를 수강중이다.)

강의를 듣기전 일단 먼저 문제를 풀었다.

내가 처음 제출한 코드는 이렇다. 다행히(?) 한번에 통과했다.

#include <iostream>
#include <vector>
#include <limits>

using namespace std;

int N;
vector<int> numV;
vector<int> oper(4, 0);
int minAns = numeric_limits<int>::max();
int maxAns = numeric_limits<int>::min();

// 입력
void input() {
    // 숫자 갯수 받기
    cin >> N;

    int temp;
    // 숫자 벡터 채우기
    for (int i = 0; i < N; i++) {
        cin >> temp;
        numV.push_back(temp);
    }
    // 연산자 벡터 채우기
    for (int i = 0; i < 4; i++) {
        cin >> oper[i];
    }
}

int sum(int a, int b) {
    return a + numV[b];
}

int sub(int a, int b) {
    return a - numV[b];
}

int mul(int a, int b) {
    return a * numV[b];
}

int di(int a, int b) {
    if (a < 0) {
        return (-1) * ((-1 * a) / numV[b]);
    }

    return a / numV[b];
}

void rec_func(int k, int ans) {
    // 연산완료
    if (k == N) {
        if (minAns > ans) {
            minAns = ans;
        }

        if (maxAns < ans) {
            maxAns = ans;
        }

        return;
    }

    // 연산
    for (int i = 0; i < 4; i++) {
        if (oper[i] == 0) {
            continue;
        }

        // 연산 후 다음단계 이동
        oper[i]--;
        switch(i) {
            case 0:
                rec_func(k + 1, sum(ans, k));
                break;
            case 1:
                rec_func(k + 1, sub(ans, k));
                break;
            case 2:
                rec_func(k + 1, mul(ans, k));
                break;
            case 3:
                rec_func(k + 1, di(ans, k));
                break;
        }

        // 연산자 변경
        oper[i]++;
        continue;
    }

}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    input();
    rec_func(1, numV[0]);

    // 결과 출력
    cout << maxAns << "\n" << minAns;
    return 0;
}

현재 수강중인 내용은 완전탐색. 완전탐색이라서기보다는 언제읽어도 무슨 코드인지 알 수 있게 지금은 가독성 중시 및 모듈화하는 연습을 하고 있다.
사실 처음에는 이게 모듈화 최선인줄 알았다.

수강 후 수정한 코드는 이렇다.

#include <iostream>
#include <vector>
#include <limits>

using namespace std;

int N;
vector<int> numV;
vector<int> operators(4, 0);
int minAns = numeric_limits<int>::max();
int maxAns = numeric_limits<int>::min();

// 입력
void input() {
    // 숫자 갯수 받기
    cin >> N;

    int temp;
    // 숫자 벡터 채우기
    for (int i = 0; i < N; i++) {
        cin >> temp;
        numV.push_back(temp);
    }
    // 연산자 벡터 채우기
    for (int i = 0; i < 4; i++) {
        cin >> operators[i];
    }
}

// 계산 함수
int calc(int operand1, int oper, int operand2) {
    switch(oper) {
        case 0:
            return operand1 + operand2;
        case 1:
            return operand1 - operand2;
        case 2:
            return operand1 * operand2;
        case 3:
            if (operand1 < 0) {
                return -1 * ((-1 * operand1) / operand2);
            }
            return operand1 / operand2;
    }
}

void rec_func(int k, int ans) {
    // 연산완료
    if (k == N) {
        if (minAns > ans) {
            minAns = ans;
        }

        if (maxAns < ans) {
            maxAns = ans;
        }

        return;
    }

    // 연산
    for (int i = 0; i < 4; i++) {
        if (operators[i] == 0) {
            continue;
        }

        // 연산 후 다음단계 이동
        operators[i]--;
        rec_func(k + 1, calc(ans, i, numV[k]));

        // 연산자 변경
        operators[i]++;
        continue;
    }

}

int main() {
    // 최적화
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    // 입력 + 연산 + 출력
    input();
    rec_func(1, numV[0]);
    cout << maxAns << "\n" << minAns;
    return 0;
}

계산을 여기저기서 할게 아니라 '계산'이라는 함수를 따로 만드는게 더 깔끔하다는 걸 알았다.

아무래도 계속 연습하는 것만이 답인 것 같다. 이 함수가 어디까지를 책임질지를 잘 고민해봐야겠다.
어찌보면 이 또한도 객체지향적인 코드를 짜는 연습이 되지 않을까 싶다. (요즘 많이 고민하는 부분 ㅎㅎ)

profile
호랑이 같이 멋진 개발자가 될 때까지 아자!

0개의 댓글