알고리즘/KOALA 알고리즘 스터디
[BOJ/C++] 14888번 연산자 끼워넣기
햄스타배
2025. 3. 22. 03:02
https://www.acmicpc.net/problem/14888

1. n 입력 받고 n개의 정수 입력받기
2. 덧셈, 뺄셈, 곱셈, 나눗셈 개수 입력받기
3. 연산자 순열 구하고 최소값 최댓값 구하기
3번에서 순열을 어떻게 구할지가 관건!
첫번째는 모든 경우를 구하는 브루트 포스를 생각할 수 있는데 만약 N이 11이면, 연산자는 10개로 모든 경우의 수는 10^10이 된다.. 시간복잡도를 생각해봤을 때 개오바텡
두번째로 생각할 수 있는 건 백트레킹!!
백트레킹은 모든 경우의 수를 탐색하다 만약 조건에 맞지 않으면 그 즉시 중단하고 이전으로 돌아가여 다시 확인하는 것을 반복하면서 원하는 조건을 찾는 알고리즘으로 안봐도 되는 케이스는 보지 않아 브루트포스보다 더 빨리 조건을 구할 수 있다

첫번째 예제를 참고해서 보자면 다음에 올 연산자를 선택할 때 이전에 나왔던 연산자라면 이전으로 돌아가 계속해서 경우의 수를 탐색한다 여기에서 포인트는 "이전에 나왔던 연산자"이기 때문에 isvisited 배열을 활용해 방문 기록을 확인하고 계속해서 탐색을 진행한다
[코드]
#include <iostream>
using namespace std;
int n; // 입력값
int arr[11];
long long min_su = 1e9, max_su = -1e9; // 출력값
char op[10], result[10];
bool isvisited[10] = {false};
void oplist(int k, int p, char o)
{
for (int i = k; i < p; i++)
{
op[i] = o;
}
}
int oper(char result[10])
{
long long sum = arr[0];
for (int i = 0; i < n - 1; i++)
{
if (result[i] == '+')
{
sum += arr[i + 1];
}
else if (result[i] == '-')
{
sum -= arr[i + 1];
}
else if (result[i] == '*')
{
sum *= arr[i + 1];
}
else
{
if (sum < 0)
{
sum = -(-sum / arr[i + 1]);
}
else
{
sum /= arr[i + 1];
}
}
}
return sum;
}
void operorder(int x)
{
// x번째에 올 연산자 구하기
if (x == n - 1)
{
if (oper(result) < min_su)
{
min_su = oper(result);
};
if (oper(result) > max_su)
{
max_su = oper(result);
}
// cout << " " << oper(result) << "\n";
return;
}
else
{
for (int i = 0; i < n - 1; i++)
{
if (!isvisited[i])
{
isvisited[i] = true;
result[x] = op[i];
operorder(x + 1);
isvisited[i] = false;
}
}
}
}
int main()
{
int plus, minus, pro, div;
cin >> n;
for (int i = 0; i < n; i++)
{
cin >> arr[i];
}
cin >> plus >> minus >> pro >> div;
// 연산자 순서대로 배열에 담기
oplist(0, plus, '+');
oplist(plus, plus + minus, '-');
oplist(minus + plus, pro + minus + plus, '*');
oplist(pro + minus + plus, pro + minus + plus + div, '/');
operorder(0);
cout << max_su << "\n"
<< min_su;
}