[백준] 2961 도영이가 만든 맛있는 음식 JavaScript

·2024년 7월 29일

문제

도영이는 짜파구리 요리사로 명성을 날렸었다. 이번에는 이전에 없었던 새로운 요리에 도전을 해보려고 한다.

지금 도영이의 앞에는 재료가 N개 있다. 도영이는 각 재료의 신맛 S와 쓴맛 B를 알고 있다. 여러 재료를 이용해서 요리할 때, 그 음식의 신맛은 사용한 재료의 신맛의 곱이고, 쓴맛은 합이다.

시거나 쓴 음식을 좋아하는 사람은 많지 않다. 도영이는 재료를 적절히 섞어서 요리의 신맛과 쓴맛의 차이를 작게 만들려고 한다. 또, 물을 요리라고 할 수는 없기 때문에, 재료는 적어도 하나 사용해야 한다.

재료의 신맛과 쓴맛이 주어졌을 때, 신맛과 쓴맛의 차이가 가장 작은 요리를 만드는 프로그램을 작성하시오.

입력

첫째 줄에 재료의 개수 N(1 ≤ N ≤ 10)이 주어진다. 다음 N개 줄에는 그 재료의 신맛과 쓴맛이 공백으로 구분되어 주어진다. 모든 재료를 사용해서 요리를 만들었을 때, 그 요리의 신맛과 쓴맛은 모두 1,000,000,000보다 작은 양의 정수이다.

출력

첫째 줄에 신맛과 쓴맛의 차이가 가장 작은 요리의 차이를 출력한다.

예제 입력

2
3 8
5 8

예제 출력

1

내가 했던 풀이 방법

  1. 입력받은 재료를 split을 통해 분할하여 신맛과 쓴맛을 배열 형태로 변환해 저장하고, min을 Infinity로 초기화한다.
  2. 0부터 N-1까지 ingredients에 신맛과 쓴맛을 각각 파라미터로 전달하고, 현재 index를 prev 값으로 보낸다. (prev 이후에 재료들만 사용하여 DFS가 무한 반복하거나 overflow 되지 않게 하기 위함)
  3. 신맛과 쓴맛의 차이가 min보다 작을 경우, min을 바꿔준다. 이때 차이는 절댓값임에 유의한다.
  4. prev 다음 재료부터 끝까지 반복하면서 각각 두 번의 DFS 재귀호출을 한다. 하나는 해당 재료를 사용하지 않는 것이고, 하나는 해당 재료를 사용하는 것이다. 해당 재료를 사용하지 않음은 신맛과 쓴맛의 차이도 없기 때문에 prev만 변경된다. 해당 재료를 사용하면 신맛은 현재값에 ×를 해주고, 쓴맛은 +를 해준다.
  5. 이를 DFS가 모두 끝날 때까지 반복한다음 min 값을 출력한다.

코드

const fs = require('fs');
let [N, ...ingredients] = fs.readFileSync(0, 'utf-8').toString().trim().split('\n');

N = Number(N);
for (let i = 0; i < N; i++) {
  ingredients[i] = ingredients[i].trim().split(' ').map(Number);
}

let min = Infinity;
function DFS(sour, bitter, prev) {
  let diff = Math.abs(sour - bitter);
  if (min > diff) min = diff;

  for (let i = prev + 1; i < N; i++) {
    DFS(sour, bitter, i);
    DFS(sour * ingredients[i][0], bitter + ingredients[i][1], i);
  }
}

for (let i = 0; i < N; i++) {
  DFS(ingredients[i][0], ingredients[i][1], i);
}

console.log(min);

회고

백트래킹은 하도 익숙해서 문제 풀이에 어려움은 없었고 신경 써줘야 하는 부분은 visited를 사용하기 애매한 백트래킹이므로 해당 재료 이후에 재료들만 신경써야 하고, 이후 재료 중 특정 재료는 사용하지 않을 수 있다는 것도 생각해주어야 한다.

profile
Frontend🍓

0개의 댓글