문제
문제
N개의 수로 이루어진 수열 A1, A2, ..., AN이 주어진다. 또, 수와 수 사이에 끼워넣을 수 있는 N-1개의 연산자가 주어진다. 연산자는 덧셈(+), 뺄셈(-), 곱셈(×), 나눗셈(÷)으로만 이루어져 있다.우리는 수와 수 사이에 연산자를 하나씩 넣어서, 수식을 하나 만들 수 있다. 이때, 주어진 수의 순서를 바꾸면 안 된다.예를 들어, 6개의 수로 이루어진 수열이 1, 2, 3, 4, 5, 6이고, 주어진 연산자가 덧셈(+) 2개, 뺄셈(-) 1개, 곱셈(×) 1개, 나눗셈(÷) 1개인 경우에는 총 60가지의 식을 만들 수 있다. 예를 들어, 아래와 같은 식을 만들 수 있다.1+2+3-4×5÷61÷2+3+4-5×61+2÷3×4-5+61÷2×3-4+5+6식의 계산은 연산자 우선 순위를 무시하고 앞에서부터 진행해야 한다. 또, 나눗셈은 정수 나눗셈으로 몫만 취한다. 음수를 양수로 나눌 때는 C++14의 기준을 따른다. 즉, 양수로 바꾼 뒤 몫을 취하고, 그 몫을 음수로 바꾼 것과 같다. 이에 따라서, 위의 식 4개의 결과를 계산해보면 아래와 같다.1+2+3-4×5÷6 = 11÷2+3+4-5×6 = 121+2÷3×4-5+6 = 51÷2×3-4+5+6 = 7N개의 수와 N-1개의 연산자가 주어졌을 때, 만들 수 있는 식의 결과가 최대인 것과 최소인 것을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 수의 개수 N(2 ≤ N ≤ 11)가 주어진다. 둘째 줄에는 A1, A2, ..., AN이 주어진다. (1 ≤ Ai ≤ 100) 셋째 줄에는 합이 N-1인 4개의 정수가 주어지는데, 차례대로 덧셈(+)의 개수, 뺄셈(-)의 개수, 곱셈(×)의 개수, 나눗셈(÷)의 개수이다.
출력
첫째 줄에 만들 수 있는 식의 결과의 최댓값을, 둘째 줄에는 최솟값을 출력한다. 연산자를 어떻게 끼워넣어도 항상 -10억보다 크거나 같고, 10억보다 작거나 같은 결과가 나오는 입력만 주어진다. 또한, 앞에서부터 계산했을 때, 중간에 계산되는 식의 결과도 항상 -10억보다 크거나 같고, 10억보다 작거나 같다.
문제 풀이
해당 문제는 백트래킹으로 풀 수 있는 문제이다. 주어지는 정수와 연산자를 가지고 만들 수 있는 최솟 값과 최댓 값을 찾아서 반환해야 하는 문제이다.
dfs(깊이 우선 탐색)를 이용하여 모든 경우의 수를 찾아내면 된다. arr 배열에 수를 저장하고, op 배열에 연산자 개수를 저장한다. dfs 함수에서는 현재까지 계산한 값(num)과 깊이(depth)를 매개변수로 받으며, depth와 n이 같아지면 모든 수를 다 계산한 것이므로 max와 min 값을 갱신하고 return 하는 방식으로 처리한다.
private static void dfs(int num, int depth) {
if (depth == n) {
max = Math.max(max, num);
min = Math.min(min, num);
return;
}
모든 경우의 수를 찾아낼 때, op 배열에 있는 연산자들 중 사용 가능한 연산자를 선택하여 계산하고, 사용한 연산자는 op 배열에서 뺀 후, 다시 추가해줍니다. 최댓값과 최솟값을 찾아내기 위해서는 각각 Integer.MIN_VALUE와 Integer.MAX_VALUE로 초기화를 해준 후, dfs 함수에서 계산한 결과와 비교하여 값을 갱신해주면 됩니다.
static int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
for (int i = 0; i < op.length; i++) {
if (op[i] > 0) {
op[i]--;
if (i == 0) dfs(num + arr[depth], depth + 1);
else if (i == 1) dfs(num - arr[depth], depth + 1);
else if (i == 2) dfs(num * arr[depth], depth + 1);
else dfs(num / arr[depth], depth + 1);
op[i]++;
}
}
나의 답안
import java.util.Scanner;
public class Main {
static int n;
static int[] arr;
static int[] op = new int[4];
static int max = Integer.MIN_VALUE, min = Integer.MAX_VALUE;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
n = sc.nextInt();
arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
for (int i = 0; i < op.length; i++) {
op[i] = sc.nextInt();
}
dfs(arr[0], 1);
System.out.println(max);
System.out.println(min);
}
private static void dfs(int num, int depth) {
if (depth == n) {
max = Math.max(max, num);
min = Math.min(min, num);
return;
}
for (int i = 0; i < op.length; i++) {
if (op[i] > 0) {
op[i]--;
if (i == 0) dfs(num + arr[depth], depth + 1);
else if (i == 1) dfs(num - arr[depth], depth + 1);
else if (i == 2) dfs(num * arr[depth], depth + 1);
else dfs(num / arr[depth], depth + 1);
op[i]++;
}
}
}
}
'BackJoon > Algorithm' 카테고리의 다른 글
(1026) 보물 (0) | 2023.04.11 |
---|---|
(11399) ATM (0) | 2023.04.11 |
(15651) N과 M(3) (0) | 2023.04.10 |
(9663) N-Queen (0) | 2023.04.10 |
(15650) N 과 M(2) (0) | 2023.04.10 |