백준 2961, 도영이가 만든 맛있는 음식 - Brute Force, Backtracking
https://www.acmicpc.net/problem/2961
풀이 ①, ② 둘 다 브루트 포스 + 백트래킹 사용,
백트래킹 구현에 약간의 차이
풀이 ①
1. 아이디어
브루트 포스 + 백트래킹: 백트래킹으로 조합(부분 집합)을 구성하고, 구성한 모든 경우를 확인
-
n 개의 재료들 중에서 1 ~ n 개 조합 (중복 X, 순서 X) 선택
- 1개 조합 선택 후, 차이 계산
- 2개 조합 선택 후, 차이 계산
... - n 개 조합 선택 후, 차이 계산
-
각 조합들에 대해 맛 최소 차이 갱신해나감
2. 자료구조
Taste[]
: 각 재료들의 신 맛, 쓴 맛List<Integer>
,ArrayList<Integer>
: 선택된 재료들
3. 시간 복잡도
- 조합(Combination): C(n, k) = n! / k! x (n-k)!
- n 최대 10에 대해 C(10, 1) + C(10, 2) + ... + C(10, 10)
= [ C(10, 1) + C(10, 2) + C(10, 3) + C(10, 4) + C(10, 5) ] x 2
= 총 1,274 개 경우 << 1억 (1초)
코드
import java.io.*;
import java.util.*;
class Taste {
public int sour; // 신 맛
public int bitter; // 쓴 맛
public Taste(int sour, int bitter) {
this.sour = sour;
this.bitter = bitter;
}
}
public class Main {
static int n; // 재료 개수
static Taste[] tastes; // 각 재료들의 신 맛, 쓴 맛
static int minDiff = Integer.MAX_VALUE; // 출력: 최소 신 맛, 쓴 맛 차이
static List<Integer> selected; // 조합: 선택된 재료들
/* C(n, k) 구성 => k 개 선택 */
static void combination(int k, int startIdx) {
if (selected.size() == k) { // k 개 재료 선택 완료
int totalSour = 1;
int totalBitter = 0;
for (int idx : selected) {
Taste taste = tastes[idx];
totalSour *= taste.sour;
totalBitter += taste.bitter;
}
int diff = Math.abs(totalSour - totalBitter);
minDiff = Math.min(minDiff, diff);
return;
}
for (int i = startIdx; i < n; i++) {
selected.add(i);
combination(k, i + 1);
// 재귀 호출 복귀 => 선택 복구
selected.remove(Integer.valueOf(i));
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringTokenizer st;
n = Integer.parseInt(br.readLine());
tastes = new Taste[n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
int sour = Integer.parseInt(st.nextToken());
int bitter = Integer.parseInt(st.nextToken());
tastes[i] = new Taste(sour, bitter);
}
// C(n, 1) ~ C(n, n)
for (int i = 1; i <= n; i++) {
selected = new ArrayList<>();
combination(i, 0);
}
System.out.println(minDiff);
}
}
풀이 ② - 재귀호출 2번: 선택 O / 선택 X
다수의 item들을 차례로 확인하면서 해당 item을 선택 O / 선택 X 하는 경우,
풀이 ②의 방식이 조금 더 직관적임
1. 아이디어
다수의 item들을 차례로 확인하면서 해당 item을 선택 O / 선택 X 하는 경우,
풀이 ②의 방식이 조금 더 직관적임
브루트 포스 + 백트래킹: 백트래킹으로 조합(부분 집합)을 구성하고, 구성한 모든 경우를 확인
-
n 개 재료들을 차례로 확인
1) idx 번째 재료를 선택하고, 그 다음 재료 확인 (재귀 호출)
2) idx 번째 재료를 선택하지 않고, 그 다음 재료 확인 (재귀 호출) -
재귀 호출 종료 조건: n 개 재료들을 모두 확인
=> 맛 차이 계산 -
예외 처리) 재료를 1개도 선택하지 않은 경우는 제외 처리
2. 자료구조
Taste[]
: 각 재료들의 신 맛, 쓴 맛List<Integer>
,ArrayList<Integer>
: 선택된 재료들
3. 시간 복잡도
-
1개 재료에 대해, 2가지 선택
- 해당 재료 선택 O
- 해당 재료 선택 X
=> 재귀 호출 2번
-
총 재귀 호출 (전체 경우의 수) = 2^10 = 1,024 << 1억 (1초)
코드
import java.io.*;
import java.util.*;
class Taste {
public int sour; // 신 맛
public int bitter; // 쓴 맛
public Taste(int sour, int bitter) {
this.sour = sour;
this.bitter = bitter;
}
}
public class Main2 {
static int n; // 재료 개수
static Taste[] tastes; // 각 재료들의 신 맛, 쓴 맛
static int minDiff = Integer.MAX_VALUE; // 출력: 최소 신 맛, 쓴 맛 차이
static List<Integer> selected = new ArrayList<>(); // 선택된 재료들
static void solution(int depth) {
if (depth == n) { // n 개 재료들을 모두 확인한 경우
if (selected.isEmpty()) // 재료를 1개도 선택하지 않은 경우는 제외
return;
int totalSour = 1;
int totalBitter = 0;
for (int idx : selected) {
Taste taste = tastes[idx];
totalSour *= taste.sour;
totalBitter += taste.bitter;
}
int diff = Math.abs(totalSour - totalBitter);
minDiff = Math.min(minDiff, diff);
return;
}
selected.add(depth); // 해당 재료 선택 O
solution(depth + 1);
selected.remove(Integer.valueOf(depth)); // 해당 재료 선택 X
solution(depth + 1);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(
new InputStreamReader(System.in)
);
StringTokenizer st;
n = Integer.parseInt(br.readLine());
tastes = new Taste[n];
for (int i = 0; i < n; i++) {
st = new StringTokenizer(br.readLine());
int sour = Integer.parseInt(st.nextToken());
int bitter = Integer.parseInt(st.nextToken());
tastes[i] = new Taste(sour, bitter);
}
solution(0);
System.out.println(minDiff);
}
}
Author And Source
이 문제에 관하여(백준 2961, 도영이가 만든 맛있는 음식 - Brute Force, Backtracking), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@silver_star/백준-2961-도영이가-만든-맛있는-음식-Brute-Force-Backtracking저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)