백준

[백준_2961번] 도영이가 만든 맛있는 음식

빙수빈수 2021. 8. 25. 20:45

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

 

2961번: 도영이가 만든 맛있는 음식

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

www.acmicpc.net

[문제]

 도영이는 짜파구리 요리사로 명성을 날렸었다. 이번에는 이전에 없었던 새로운 요리에 도전을 해보려고 한다. 지금 도영이의 앞에는 재료가 N개 있다. 도영이는 각 재료의 신맛 S와 쓴맛 B를 알고 있다. 여러 재료를 이용해서 요리할 때, 그 음식의 신맛은 사용한 재료의 신맛의 곱이고, 쓴맛은 합이다.

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

 

[입력 조건]

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

 

[코드]

import java.util.*;

public class BaekJoon_2961 {
	static int n,min=Integer.MAX_VALUE;
	static int[][] food;
	static boolean[] visited;
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Scanner sc=new Scanner(System.in);
		n=sc.nextInt();
		food=new int[n][2];
		visited=new boolean[n];
		
		for(int i=0;i<n;i++) {
			food[i][0]=sc.nextInt(); // 쓴 맛
			food[i][1]=sc.nextInt(); // 단 맛
		}
		
		dfs(0);
		System.out.println(min);
	}
	
	static void dfs(int depth) {
		if(depth==food.length) {
			int sour=1; 
			int butter=0; 
			int count=0;
			for(int i=0;i<visited.length;i++) {
				if(visited[i]) {
					count++;
					sour*=food[i][0]; // 쓴맛 
					butter+=food[i][1]; // 단맛
				}
			}
			
			// 아무 음식도 선택되지 않은 경우는 return
			if(count==0)
				return;
			
			// 최솟값 갱신
			min=Math.min(min, Math.abs(butter-sour));
			return;
		}
		
		// 현재 음식은 선택한 경우 탐색
		visited[depth]=true;
		dfs(depth+1);
		
		// 현재 음식은 선택하지 않은 경우 탐색
		visited[depth]=false;
		dfs(depth+1);
	}
}

 

[고찰]

 이번 문제는 음식을 1개부터 n개까지 선택 할 수 있는 모든 경우의 수를 탐색하여 그 중 신맛과 단맛의 조화가 가장 최소가 되는 경우를 찾는 문제였다. 선택해야 하는 음식의 개수와 종류가 달라지기 때문에 어떻게 모든 경우를 탐색할 수 있을까 고민해보았다. 그 결과 이번 문제를 푸는 핵심은 '현재 음식을 선택하냐 선택하지 않느냐' 였다. 이를 백트래킹으로 구현하면 쉽게 해결할 수 있다. 현재 음식을 선택한 채로 깊이를 1 늘려 재귀호출 하거나 현재 음식을 선택하지 않은 채로 깊이를 1 늘려 재귀호출 하면 된다. 깊이가 음식의 개수와 같아진다면 선태된 음식의 신맛과 단맛을 계산해 최솟값을 갱신해주면 된다. 

'백준' 카테고리의 다른 글

[백준_2023번] 신기한 소수  (0) 2021.08.27
[백준_16198번] 에너지 모으기  (0) 2021.08.27
[백준_16922번] 로마 숫자 만들기  (0) 2021.08.25
[백준_11559번] Puyo Puyo  (0) 2021.08.25
[백준_11057번] 오르막 수  (0) 2021.08.25