알고리즘/PS - 백준

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

excited-hyun 2021. 9. 10. 17:47
반응형

https://www.acmicpc.net/problem/14888

 

14888번: 연산자 끼워넣기

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

www.acmicpc.net

 

문제

N개의 수로 이루어진 수열 A1, A2, ..., AN이 주어진다. 또, 수와 수 사이에 끼워넣을 수 있는 N-1개의 연산자가 주어진다. 연산자는 덧셈(+), 뺄셈(-), 곱셈(×), 나눗셈(÷)으로만 이루어져 있다.

우리는 수와 수 사이에 연산자를 하나씩 넣어서, 수식을 하나 만들 수 있다. 이때, 주어진 수의 순서를 바꾸면 안 된다.

예를 들어, 6개의 수로 이루어진 수열이 1, 2, 3, 4, 5, 6이고, 주어진 연산자가 덧셈(+) 2개, 뺄셈(-) 1개, 곱셈(×) 1개, 나눗셈(÷) 1개인 경우에는 총 60가지의 식을 만들 수 있다. 예를 들어, 아래와 같은 식을 만들 수 있다.

  • 1+2+3-4×5÷6
  • 1÷2+3+4-5×6
  • 1+2÷3×4-5+6
  • 1÷2×3-4+5+6

식의 계산은 연산자 우선 순위를 무시하고 앞에서부터 진행해야 한다. 또, 나눗셈은 정수 나눗셈으로 몫만 취한다. 음수를 양수로 나눌 때는 C++14의 기준을 따른다. 즉, 양수로 바꾼 뒤 몫을 취하고, 그 몫을 음수로 바꾼 것과 같다. 이에 따라서, 위의 식 4개의 결과를 계산해보면 아래와 같다.

  • 1+2+3-4×5÷6 = 1
  • 1÷2+3+4-5×6 = 12
  • 1+2÷3×4-5+6 = 5
  • 1÷2×3-4+5+6 = 7

N개의 수와 N-1개의 연산자가 주어졌을 때, 만들 수 있는 식의 결과가 최대인 것과 최소인 것을 구하는 프로그램을 작성하시오.

입력

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

출력

첫째 줄에 만들 수 있는 식의 결과의 최댓값을, 둘째 줄에는 최솟값을 출력한다. 연산자를 어떻게 끼워넣어도 항상 -10억보다 크거나 같고, 10억보다 작거나 같은 결과가 나오는 입력만 주어진다. 또한, 앞에서부터 계산했을 때, 중간에 계산되는 식의 결과도 항상 -10억보다 크거나 같고, 10억보다 작거나 같다.

 

풀이

수의 개수가 11 이하로 매우 작기 때문에 연산자를 하나씩 추가하면서 모든 경우의 수를 확인해봐도 됩니다.

따라서 재귀함수를 이용해 연산자로 만들어지는 모든 경우의 수를 확인하는 방식으로 구현하였습니다.

 

  1. 수의 개수를 입력받고 nums배열에 각각의 수를 입력 받아 저장합니다. 그런 뒤 oprator배열에 차례로 +,-,*,/ 수를 저장합니다.
  2. 최댓값과 최솟값을 각각 -10억, 10억으로 초기화 해둡니다.
  3. 우선 아무런 연산자도 추가하지 않은 상태로 재귀함수를 호출합니다.
  4. 재귀함수 내에서는 다음과 같은 연산을 수행합니다.
    1. 연산자를 모두 추가한지 확인하여 모두 추가한 경우엔 수식을 계산하는 함수를 호출합니다.
    2. +, -, *, / 각각의 연산자의 남은 개수가 0이 아닌 경우에만 해당하는 연산자를 formula String의 뒤에 추가하고 해당 연산자의 남은 개수를 1 감소시킨 뒤 재귀함수를 호출합니다.
    3. 재귀호출에서 돌아오면 해당 연산자의 수를 다시 원래 값으로 만들어주어야 합니다.
  5. 수식을 계산하는 함수에서는 다음과 같은 연산을 수행합니다.
    1. 우선 result 값에 nums[0] 값을 넣습니다.
    2. 그런 뒤 i=1 부터 i<n인 동안 반복하는 for문을 이용해 연산자에 해당하는 연산을 수행합니다.
    3. 계산 완료 후에는 최댓값, 최솟값과 비교해 값을 업데이트합니다.
  6. 모든 연산 완료후 최댓값, 최솟값을 출력하고 종료합니다.

 

import java.util.Scanner;

public class Main {

	static int n;
	static int[] nums = new int[12];
	
	static int maxA = -1000000000;
	static int minA = 1000000000;

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);
		n = sc.nextInt();

		for(int i=0; i<n; i++)
			nums[i] = sc.nextInt();

		int[] operand = new int[4];
		for(int i=0; i<4; i++)
			operand[i] = sc.nextInt();

		String temp = "";
		addOper(0, temp, operand);
		
		System.out.println(maxA);
		System.out.println(minA);

	}

	// 연산자 차례로 추가하는 함수 
	static void addOper(int cnt, String formula, int[] operand) {
		//연산자 모두 생성 완료!
		if(cnt == n-1)
			calc(formula);

		//각각의 연산자 추가 
		// plus +
		if(operand[0]!=0) {
			operand[0]--;
			addOper(cnt+1, formula+"+", operand);
			operand[0]++;
		}
		// minus -
		if(operand[1]!=0) {
			operand[1]--;
			addOper(cnt+1, formula+"-", operand);
			operand[1]++;
		}
		// mul *
		if(operand[2]!=0) {
			operand[2]--;
			addOper(cnt+1, formula+"*", operand);
			operand[2]++;
		}
		// div /
		if(operand[3]!=0) {
			operand[3]--;
			addOper(cnt+1, formula+"/", operand);
			operand[3]++;
		}


	}

	// 수식 계산하는 함수
	static void calc(String formula) {
		int result = nums[0];
		for(int i=1; i<n; i++) {
			char operand = formula.charAt(i-1);

			if(operand == '+') {
				result += nums[i];
			}
			else if(operand == '-') {
				result -= nums[i];
			}
			else if(operand == '*') {
				result *= nums[i];
			}
			else if(operand == '/') {
				result /= nums[i];
			}
		}
		if(result > maxA)
			maxA = result;
		if(result < minA)
			minA = result;
	}
}
728x90
반응형