문제
세준이는 양수와 +, -, 그리고 괄호를 가지고 식을 만들었다. 그리고 나서 세준이는 괄호를 모두 지웠다.
그리고 나서 세준이는 괄호를 적절히 쳐서 이 식의 값을 최소로 만들려고 한다.
괄호를 적절히 쳐서 이 식의 값을 최소로 만드는 프로그램을 작성하시오.
입력
첫째 줄에 식이 주어진다. 식은 ‘0’~‘9’, ‘+’, 그리고 ‘-’만으로 이루어져 있고, 가장 처음과 마지막 문자는 숫자이다. 그리고 연속해서 두 개 이상의 연산자가 나타나지 않고, 5자리보다 많이 연속되는 숫자는 없다. 수는 0으로 시작할 수 있다. 입력으로 주어지는 식의 길이는 50보다 작거나 같다.
출력
첫째 줄에 정답을 출력한다.
입출력 예시
입력 1
55-50+40
출력 1
-35
입력 2
10+20+30+40
출력 2
100
풀이
'use strict';
const fs = require('fs');
// 백준 제출 할 때 주석 제거
// const readFileSyncAddress = '/dev/stdin';
// VSC 테스트 할 때 주석 제거
const readFileSyncAddress = 'input.txt';
const input = fs.readFileSync(readFileSyncAddress).toString().trim().split('\n');
function plusAll(eq) {
const numberList = eq.split('+').map(Number);
return numberList.reduce((acc, curr) => acc + curr);
}
function solution(input) {
const minusArea = input.split('-');
let result = plusAll(minusArea.shift());
minusArea.forEach(area => {
result -= plusAll(area);
});
return result;
}
console.log(solution(input[0]));
💡 문제의 핵심
식의 값을 최소로 만드는 데 가장 중요한 연산자는 바로 마이너스(-)다.
- 더하기(+)는 값을 최소화하는 데 전혀 영향을 주지 않는다. 숫자끼리 모두 더하면 된다.
- 하지만 마이너스(-)는 어떻게 식을 구분하고 괄호를 묶느냐에 따라 결과 값이 크게 달라진다.
여기서 "구분"이라는 말이 나온 순간, 각 구간의 최적해가 모여 전체 최적해가 되는 "그리디 알고리즘"을 떠올릴 수 있다!
즉, 이 문제는 "마이너스를 기준으로 식을 구분해서 부분 최적해를 구한 후 합치는 방식"의 전형적인 그리디 문제이다.
📌 어떻게 마이너스로 식을 구분할까?
const minusArea = input.split('-');
주어진 식을 split을 통해 마이너스(-) 기준으로 나누면, 아래와 같이 여러 그룹으로 나눌 수 있다.
30 - 15 + 53 + 3 - 2 -> 30 / 15 + 53 + 3 / 2
각각의 그룹은 모두 더하기로 이루어진 식이 된다!
function plusAll(eq) {
const numberList = eq.split('+').map(Number);
return numberList.reduce((acc, curr) => acc + curr);
}
각 그룹을 모두 계산해주면
- 첫 번째 그룹: 30
- 두 번째 그룹: (15 + 53 + 3) → 71
- 세 번째 그룹: 2
이제 각 그룹의 값들을 모두 빼주면 30 - 71 - 2 = -43으로 최소값이 나오게 된다!
'알고리즘' 카테고리의 다른 글
[ 백준 ] 11660 구간 합 구하기 5 - JavaScript (0) | 2025.03.31 |
---|---|
[ 백준 ] 12933 오리 - JavaScript (0) | 2025.03.29 |
[ 백준 ] 10799 쇠막대기 - JavaScript (1) | 2025.01.07 |
[ 백준 ] 1966 프린터 큐 - JavaScript (0) | 2025.01.07 |
[ 백준 ] 10866 덱 - JavaScript (2) | 2025.01.04 |