Koala - 9기/코딩테스트 준비 스터디

[백준/C++] 14888번 연산자 끼워넣기

hyss 2023. 1. 7. 22:17

14888번: 연산자 끼워넣기 (acmicpc.net)

 

14888번: 연산자 끼워넣기

첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 

www.acmicpc.net

문제분석

N개의 수로 이루어진 수열 A1, A2, ..., AN과 수와 수 사이에 끼워넣을 수 있는 N-1개의 연산자(+, -, *, /)가 주어졌을 때, 최대값과 최소값을 구하는 문제다.

이 때, 주어진 수의 순서는 바꿀 수 없고, 식의 계산은 연산자 우선 순위를 무시하고 앞에서부터 차례대로 진행해야 한다.

- 입력: 첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 곱셈(×)의 개수, 나눗셈(÷)의 개수이다. 

- 출력: 첫째 줄에 만들 수 있는 식의 결과의 최댓값을, 둘째 줄에는 최솟값을 출력한다.

 

코드

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int N;
int A[11];
int op[4];

ll maxResult = -10e10;
ll minResult = 10e10;

void dfs(int opNum, int res) {
	if (opNum == N - 1) { //기저사례 (N-1개의 연산자를 사용했으면 종료)
		if (res > maxResult) maxResult = res;
		if (res < minResult) minResult = res;
		return;
	}

	for (int i = 0; i < 4; i++) {
		if (op[i] > 0) { //해당 연산자 개수가 남아있으면 사용
			op[i]--; //해당 연산자 개수 줄이고
			opNum++; //사용한 총 연산자 개수 늘리고
			if (i == 0) dfs(opNum, res + A[opNum]); //사용한 총 연산자 개수를 늘리고 결과값과 함께 다음으로
			else if (i == 1) dfs(opNum, res - A[opNum]);
			else if (i == 2) dfs(opNum, res * A[opNum]);
			else if (i == 3) dfs(opNum, res / A[opNum]);
			op[i]++; //다른 연산자도 써보기 위해 초기화
			opNum--;
		}
	}

	return;
}

void solveProblem() {
	dfs(0, A[0]);
	cout << maxResult << "\n" << minResult;
}

void getInput() {
	cin >> N;
	for (int i = 0; i < N; i++) cin >> A[i];
	for (int i = 0; i < 4; i++) cin >> op[i];
}

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

	getInput();
	solveProblem();

	return 0;
}

문제풀이

재귀를 통한 Bruteforce 방식으로 문제를 해결했다.

1. 연산자의 개수는 op[] 배열에, 수열은 A[] 배열에 입력받는다.

2. dfs 함수를 실행하는데, 아직 연산자를 하나도 사용하지 않았으므로 opNum=0, 결과값(res)은 수열의 첫 번째 값을 넘긴다. 

3. 4개의 연산자에 대해서 for loop을 돌리면서, +, -, *, /를 순차적으로 모두 사용해본다.

4. 3번의 for loop을 수행하면서, 지금까지 사용한 연산자의 총 개수(opNum)와 연산의 결과값(res ? A[opNum])을 다음 재귀함수로 넘겨주다가, 사용한 연산자의 총 개수가 N-1개가 된다면(모두 사용했다면) 재귀를 마치고, 이 때의 결과값이 최대값보다 크다면 maxResult에, 최소값보다 작다면 minResult에 기록한다. (이 때, ?는 +, -, *, / 중 하나)

4. 모든 경우의 수를 따져보기 위해 for loop을 1회 수행할 때마다 op[i]와 opNum을 다시 되돌리면서 N-1개의 연산자에 대해서 모두 for loop을 돌릴 수 있도록 한다. 

5. 모든 재귀를 마치면 maxResult와 minResult를 출력하고 끝낸다.