메모리: 19636 KB, 시간: 156 ms
백트래킹, 브루트포스 알고리즘
2024년 11월 14일 16:29:06
식재료 N개 중에서 몇 개를 선택해서 이들의 영양분(단백질, 탄수화물, 지방, 비타민)이 일정 이상이 되어야 한다. 아래 표에 제시된 6가지의 식재료 중에서 몇 개를 선택해서 이들의 영양분의 각각 합이 최소 100, 70, 90, 10가 되도록 하는 경우를 생각해보자. 이 경우 모든 재료를 선택하면 쉽게 해결되지만, 우리는 조건을 만족시키면서도 비용이 최소가 되는 선택을 하려고 한다.
| 재료 | 단백질 | 지방 | 탄수화물 | 비타민 | 가격 |
|---|---|---|---|---|---|
| 1 | 30 | 55 | 10 | 8 | 100 |
| 2 | 60 | 10 | 10 | 2 | 70 |
| 3 | 10 | 80 | 50 | 0 | 50 |
| 4 | 40 | 30 | 30 | 8 | 60 |
| 5 | 60 | 10 | 70 | 2 | 120 |
| 6 | 20 | 70 | 50 | 4 | 40 |
예를 들어, 식재료 1, 3, 5를 선택하면 영양분은 100, 145, 130, 10으로 조건을 만족하지만 가격은 270이 된다. 대신 2, 3, 4를 선택하면 영양분의 합은 110, 130, 90, 10, 비용은 180이 되므로, 앞의 방법보다는 더 나은 선택이 된다.
입력으로 식재료 표가 주어졌을 때, 최저 영양소 기준을 만족하는 최소 비용의 식재료 집합을 찾아야 한다.
/**
* Author: nowalex322, Kim HyeonJae
*/
import java.io.*;
import java.util.*;
public class Main {
class Ingredient{
int protein;
int fat;
int carbohydrate;
int vitamin;
int cost;
public Ingredient(int protein, int fat, int carbohydrate, int vitamin, int cost){
this.protein = protein;
this.fat = fat;
this.carbohydrate = carbohydrate;
this.vitamin = vitamin;
this.cost = cost;
}
}
static BufferedReader br;
static BufferedWriter bw;
static StringTokenizer st;
static int N, min[] = new int [4], res = Integer.MAX_VALUE;
static Map<Integer, Ingredient> ingredients = new HashMap<Integer, Ingredient>();
static List<Integer> currChoosed = new ArrayList<Integer>();
static List<Integer> resIngredient = new ArrayList<Integer>();
public static void main(String[] args) throws Exception {
new Main().solution();
}
public void solution() throws Exception {
br = new BufferedReader(new InputStreamReader(System.in));
// br = new BufferedReader(new InputStreamReader(new FileInputStream("input.txt")));
bw = new BufferedWriter(new OutputStreamWriter(System.out));
N = Integer.parseInt(br.readLine());
st = new StringTokenizer(br.readLine());
for(int i=0; i<4; i++) {
min[i] = Integer.parseInt(st.nextToken());
}
for(int i=0; i<N; i++) {
st = new StringTokenizer(br.readLine());
int protein = Integer.parseInt(st.nextToken());
int fat = Integer.parseInt(st.nextToken());
int carbohydrate = Integer.parseInt(st.nextToken());
int vitamin = Integer.parseInt(st.nextToken());
int cost = Integer.parseInt(st.nextToken());
ingredients.put(i, new Ingredient(protein, fat, carbohydrate, vitamin, cost));
}
dfs(0, 0, 0, 0, 0, 0);
if(res == Integer.MAX_VALUE) {
System.out.println(-1);
return;
}
System.out.println(res);
for(int i=0; i<resIngredient.size(); i++) {
System.out.print(resIngredient.get(i) + 1 + " " );
}
bw.flush();
bw.close();
br.close();
}
private void dfs(int depth, int sumProtein, int sumFat, int sumCarbo, int sumVitamin, int sumCost) {
if(sumCost > res) return;
if(sumProtein >= min[0] && sumFat >= min[1] && sumCarbo >= min[2] && sumVitamin >= min[3]) {
if(res > sumCost) {
res = sumCost;
resIngredient = new ArrayList<Integer>(currChoosed);
}
return;
}
if(depth >= N) return;
currChoosed.add(depth);
Ingredient ingredient = ingredients.get(depth);
dfs(depth + 1,
sumProtein + ingredient.protein,
sumFat + ingredient.fat,
sumCarbo + ingredient.carbohydrate,
sumVitamin + ingredient.vitamin,
sumCost + ingredient.cost);
currChoosed.remove(Integer.valueOf(depth));
dfs(depth +1, sumProtein, sumFat, sumCarbo, sumVitamin, sumCost);
}
}