[백준/JAVA] 14888번 : 연산자 끼워넣기(BruteFroce, 순열)

2023. 2. 12. 17:52문제풀이/순열

 

문제

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

 

14888번: 연산자 끼워넣기

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

www.acmicpc.net

 

 

 

 

 

풀이

주어진 연산자들의 순열을 순차적으로 탐색하며 최솟값과 최댓값을 찾는다.

연산자들의 다음 순열을 찾아 나가므로, 연산자 배열을 string이 아닌 int 배열로 만든다.

숫자 n개가 주어질 때, 연산자의 총 개수는 n-1개이므로, 연산자 배열의 길이는 n-1이다.

+를 0, -를 1, x를 2, %를 3으로 하여 연산자 배열에 저장한다.

연산자를 배열로 저장하는 코드는 다음과 같다.

//연산자 배열
int[] operators = new int[n-1];

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

int idx = 0;
for(int i = 0; i<4; i++){
    int k = sc.nextInt();
    for(int j = 0; j<k; j++) {
        operators[idx] = i;
        idx++;
    }
}

 

 

이제, 연산자 순열의 다음 순열을 구해보자. 

private static boolean next_perm(int[] operators){
	int i = operators.length-1;

	//내림차순의 시작점을 구한다
    while(i>0 && operators[i-1]>=operators[i]) i--;

	//다음 순열은 존재하지 않으므로 false
    if(i<=0) return false;

    int j = operators.length-1;

	//i-1번째 수보다 큰 수 중 가장 index값이 큰 숫자를 구한다
    while(operators[j]<=operators[i-1])
        j--;

	//i-1번째 수와 j번째 수를 바꾼다
    swap(i-1, j, operators);
    
    j = operators.length-1;

	//i번째부터의 숫자는 모두 오름차순이 되어야 한다
    while(i<j){
        swap(i, j, operators);
        i++;
        j--;
    }
    return true;
}

 

 

연산자의 다음 순열을 구해, 식을 계산하는 코드는 다음과 같다.

private static int cal(int[] nums, int[] operators){
    int result = 0;

    for(int i = 0; i<nums.length-1; i++){
        if(i==0) result = nums[i];
        if(operators[i] == 0)
            result += nums[i+1];
        else if(operators[i] == 1)
            result -= nums[i+1];
        else if(operators[i] == 2)
            result = result *nums[i+1];
        else if(operators[i] == 3)
            result /= nums[i+1];
    }
    return result;
}

 

 

다음 순열이 없을 때까지 연산자 순열을 통해 계산된 결과를 리스트에 저장하고, 최댓값, 최솟값을 출력하면 된다.

 

 

 

 

 

코드

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Main {
    private static boolean next_perm(int[] operators){
        int i = operators.length-1;

        while(i>0 && operators[i-1]>=operators[i]) i--;

        if(i<=0) return false;

        int j = operators.length-1;

        while(operators[j]<=operators[i-1])
            j--;

        swap(i-1, j, operators);
        j = operators.length-1;

        while(i<j){
            swap(i, j, operators);
            i++;
            j--;
        }
        return true;
    }

    private static void swap(int i, int j, int[] arr){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

    private static int cal(int[] nums, int[] operators){
        int result = 0;

        for(int i = 0; i<nums.length-1; i++){
            if(i==0) result = nums[i];
            if(operators[i] == 0)
                result += nums[i+1];
            else if(operators[i] == 1)
                result -= nums[i+1];
            else if(operators[i] == 2)
                result = result *nums[i+1];
            else if(operators[i] == 3)
                result /= nums[i+1];
        }
        return result;
    }

    public static void main(String[] args){
        List<Integer> results = new ArrayList<Integer>();
        Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        //숫자 배열
        int[] nums = new int[n];

        //연산자 배열
        int[] operators = new int[n-1];

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

        int idx = 0;
        for(int i = 0; i<4; i++){
            int k = sc.nextInt();
            for(int j = 0; j<k; j++) {
                operators[idx] = i;
                idx++;
            }
        }


        do {
            results.add(cal(nums, operators));
        } while (next_perm(operators));

        System.out.println(Collections.max(results));
        System.out.println(Collections.min(results));
    }
}

'문제풀이 > 순열' 카테고리의 다른 글

[백준/JAVA] 2529번 : 부등호(BruteFroce, 순열)  (0) 2023.02.11