메모리: 14184 KB, 시간: 100 ms
백트래킹, 비트마스킹, 브루트포스 알고리즘
2024년 8월 7일 23:45:10
도영이는 짜파구리 요리사로 명성을 날렸었다. 이번에는 이전에 없었던 새로운 요리에 도전을 해보려고 한다.
지금 도영이의 앞에는 재료가 N개 있다. 도영이는 각 재료의 신맛 S와 쓴맛 B를 알고 있다. 여러 재료를 이용해서 요리할 때, 그 음식의 신맛은 사용한 재료의 신맛의 곱이고, 쓴맛은 합이다.
시거나 쓴 음식을 좋아하는 사람은 많지 않다. 도영이는 재료를 적절히 섞어서 요리의 신맛과 쓴맛의 차이를 작게 만들려고 한다. 또, 물을 요리라고 할 수는 없기 때문에, 재료는 적어도 하나 사용해야 한다.
재료의 신맛과 쓴맛이 주어졌을 때, 신맛과 쓴맛의 차이가 가장 작은 요리를 만드는 프로그램을 작성하시오.
첫째 줄에 재료의 개수 N(1 ≤ N ≤ 10)이 주어진다. 다음 N개 줄에는 그 재료의 신맛과 쓴맛이 공백으로 구분되어 주어진다. 모든 재료를 사용해서 요리를 만들었을 때, 그 요리의 신맛과 쓴맛은 모두 1,000,000,000보다 작은 양의 정수이다.
첫째 줄에 신맛과 쓴맛의 차이가 가장 작은 요리의 차이를 출력한다.
이 문제에서 생각해야 할 가장 중요한 건 경우의 수라고 생각한다.
이 문제는 신맛과 쓴맛의 차이가 가장 작은 요리의 차이를 구해야 하는 문제이다.
이는 두가지 경우를 통해 값을 찾아나갈 수 있다.
i번 재료를 넣는다.i번 재료를 넣지 않는다.재료의 개수 N(1 ≤ N ≤ 10)는 최대 10개라고 나와있다.
즉 각 재료를 넣을지 말지를 모두 검사해주면서 모든 경우의 수를 따져가며 값을 찾으면 된다!
필자는 "모든 재료를 사용해서 요리를 만들었을 때, 그 요리의 신맛과 쓴맛은 모두 1,000,000,000보다 작은 양의 정수이다." 라는 설명에서 혹여나
int범위를 넘길까long으로 각각의 변수를 설정했다.
하지만 다른 여러 풀이를 보니 굳이long으로 바꿀 필요는 없어보인다.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class baekjoon_2961 {
static long[][] taste;
static long ans=Long.MAX_VALUE;
static int n;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st;
n = Integer.parseInt(br.readLine());
taste = new long[n][2];
for(int i=0; i<n; i++) {
st = new StringTokenizer(br.readLine());
taste[i][0]=Integer.parseInt(st.nextToken());
taste[i][1]=Integer.parseInt(st.nextToken());
}
backtracking(0,1,0,0);
System.out.println(ans);
}
public static void backtracking(int cnt,long sour, long bitter,int select) {
if(cnt==n) {
if(select!=0 && Math.abs(sour - bitter)<ans) {
ans = Math.abs(sour - bitter);
}
return;
}
//두가지 경우 - cnt번 재료를 사용할 것인지 아닌지
backtracking(cnt+1,sour*taste[cnt][0],bitter+taste[cnt][1],select+1);
backtracking(cnt+1,sour,bitter,select);
}
}