알고리즘 문제) BOJ 19942. 다이어트
문제 요약
- 식재료 N개 중에서 단백질, 탄수화물, 지방, 비타민이 일정 이상 되도록 재료를 선할 때, 비용이 최소가 되는 경우 찾기
시간 제한
- 2초
입력
- 식재료 개수 N
- 3≤N≤15
- 단백질, 지방, 탄수화물, 비타민 최소 영양성분인 mp,mf,ms,mv가 주어짐
- 0≤mp,mf,ms,mv≤500
- mp+mf+ms+mv > 0
- 다음 N개의 줄에 i번째 식재료의 단백질, 지방, 탄수화물, 비타민과 가격이 주어짐 pi, fi, si, vi, ci
- 0≤pi,fi,si,vi,ci≤500
- 번호는 1번부터 시작
출력
- 최소비용 출력
- 최소 비용 식재료의 번호를 오름차순으로 출력
- 없다면 -1만 출력
접근법
- 1~N개를 골랐을 때 최소 기준을 충족하고, 그 중 최소 비용인 경우를 찾아야한다.
- N의 범위가 15까지 가능하므로 최대 32768가지 경우를 살핌…
코드
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[] standard;
static int[][] foods;
static int[] selected;
static ArrayList<String> ansFoods = new ArrayList<>();
static int answer = Integer.MAX_VALUE;
static void recur(int cur, int cnt) {
if (cur == N + 1) {
int p = 0, f = 0, s = 0, v = 0, c = 0;
for (int i = 0; i < cnt; i++) {
p += foods[selected[i]][0];
f += foods[selected[i]][1];
s += foods[selected[i]][2];
v += foods[selected[i]][3];
c += foods[selected[i]][4];
}
if (p < standard[0] || f < standard[1] || s < standard[2] || v < standard[3]) {
return;
}
if (answer >= c) {
if (answer > c) {
answer = c;
ansFoods.clear();
}
String str = "" ;
for (int i = 0; i < cnt; i++) {
str += selected[i] + " ";
}
ansFoods.add(str);
}
return;
}
selected[cnt] = cur;
recur(cur + 1, cnt + 1);
selected[cnt] = 0;
recur(cur + 1, cnt);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
N = Integer.parseInt(br.readLine());
standard = new int[4];
st = new StringTokenizer(br.readLine());
for (int i = 0; i < 4; i++) {
standard[i] = Integer.parseInt(st.nextToken());
}
foods = new int[N + 1][5];
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < 5; j++) {
foods[i][j] = Integer.parseInt(st.nextToken());
}
}
selected = new int[N];
recur(1, 0);
if (answer == Integer.MAX_VALUE) {
bw.write("-1");
} else {
bw.write(answer + "\\n");
Collections.sort(ansFoods);
bw.write(String.valueOf(ansFoods.get(0)));
}
bw.flush();
bw.close();
br.close();
}
}
알고리즘 문제) BOJ 1497. 기타콘서트
문제 요약
- 최대한 많은 곡을 제대로 연주하려고 할 때 필요한 기타의 최소 개수 구하기
- 만약 다 연주할 수 있다면 다 연주하는 쪽으로 필요한 기타 최소 개수 구하기
시간 제한
- 2초
입력
- 기타 개수 N 곡의 개수M
- 1≤N≤10
- 1≤M≤50
- N개의 줄에 기타 이름과 기타가 연주할 수 있는 곡의 정보가 주어짐
- Y : 연주 가능, N : 연주 불가능
- 기타 이름은 알파벳 대문자로 길이가 2이상 50 이하
- 기타 이름이 같은 경우는 X
출력
- 필요한 기타 개수 출력
- 만약 연주할 수 있는 곡이 없다면 -1 출력
접근법
- 기타를 선택하는 모든 경우의 수를 본다(N이 10이하므로 완탐 가능)
- 이때 연주할 수 있는 곡의 개수 최댓값을 갱신한다.
- 만약 같은 경우가 있다면 기타 개수가 최소인 쪽으로 기타 개수 갱신
코드
import java.io.*;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static int N, M; // 기타 개수, 곡의 개수
static String[][] arr; // 기타 이름과 연주할 수 있는 곡 정보
static int[] selected; // 정답 후보를 담을 배열(후보의 인덱스를 원소로 갖는다)
static boolean[] visited; // 연주할 수 있는 곡의 개수 체크(이미 체크한 경우 중복 카운팅 방지)
static int answer = 1000000000; // 필요한 기타 개수(최솟값으로 갱신)
static int playSongs = 0; // 연주 간으한 곡 개수(최대값 갱신)
static void recur(int cur, int cnt) {
// cur : 현재 가리키고 있는 후보 인덱스
// cnt : 현재까지 정답 후보에 올려놓은 개수
// canPlay : 연주할 수 있는 곡의 개수
if (cur == N) {
// 후보군 끝까지 탐색했을 때
int canPlay = 0; // 연주할 수 있는 곡
for (int i = 0; i < cnt; i++) {
for (int j = 0; j < M; j++) {
if (arr[selected[i]][1].charAt(j) == 'Y') {
// 연주할 수 있다면
if (visited[j]) continue; // 이미 체크한 곡이라면 pass
visited[j] = true; // 아니라면 체크해주고
canPlay++; // 연주 가능한 곡 개수 +1
}
}
}
if (playSongs == canPlay) {
// 연주 가능한 곡이 현재까지 연주 가능 곡과 같다면
// 기타 개수 최솟값으로 갱신
answer = Math.min(answer, cnt);
} else if (playSongs < canPlay) {
// 연주 가능한 곡이 더 크다면 갱신해주고, 기타 개수도 현재 개수로 초기화
playSongs = canPlay;
answer = cnt;
}
// visited 배열 false로 초기화
Arrays.fill(visited, false);
return;
}
// 현재 가리키는 후보를 선택할 경우
selected[cnt] = cur;
recur(cur + 1, cnt + 1);
// 햔재 가리키는 후보를 패스할 경우
selected[cur] = -1;
recur(cur + 1, cnt);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
// N, M 입력 받기
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
// 기타 이름과 연주곡 정보 입력 받기
arr = new String[N][2];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
arr[i][0] = st.nextToken();
arr[i][1] = st.nextToken();
}
selected = new int[N];
visited = new boolean[M];
recur(0, 0);
if (playSongs == 0) bw.write("-1");
else bw.write(String.valueOf(answer));
bw.flush();
bw.close();
br.close();
}
}
알고리즘 문제) BOJ 16457. 단풍잎 이야기
문제 요약
- m개의 퀘스트들이 주어지고 각각의 퀘스트는 k개의 스킬을 사용해야 함
- n개의 키에 어떤 스킬들을 배치할 때 가장 많은 양의 퀘스트를 깰 수 있는지 찾기
시간 제한
- 1초
입력
- 키의 개수 n, 퀘스트 개수 m, 퀘스트 당 사용해야하는 스킬 개수 k
- n은 10이하 양수
- k는 n이하 양수
- m은 100이하 양수
- m개의 줄에 각각 퀘스트들이 사용해야하는 스킬들이 주어짐
- 스킬이름은 1~2n의 정수
출력
- 가장 최적의 키배치를 했을 때 최대로 깰 수 있는 퀘스트 개수?
접근법
키에는 1부터 2n의 키를 배치할 수 있다.
즉, 1~2n의 키중 n개를 배치하는 경우를 찾고, 이때 꺨수 있는 퀘스트 수를 카운팅하고 최댓값으로 갱신한다.
백트랙킹 가지치기로 cnt > n인 경우 return 하기
코드
import java.io.*;
import java.util.StringTokenizer;
public class Main {
static int N, M, K; // 키 개수, 퀘스트 개수, 스킬 수
static int[][] quests; // 퀘스트 스킬 정보
static int[] selected; // 배치한 스킬 이름(번호)
static int answer = 0; // 최대로 깰 수 있는 스킬 개수
static void recur(int cur, int cnt) {
// 키 배치를 N개 초과할 때 return -> N개만 배치 가능하므로
if (cnt > N) return;
if (cur == 2 * N + 1) {
// 키가 2*N까지 배치될 수 있기때문에 다 배치하고나서 2*N + 1일 때 체크
// 깰 수 있는 퀘스트 수 카운팅
int check, clear = 0;
for (int i = 0; i < M; i++) {
// 퀘스트 별로 돌면서
check = 0; // 깰 수 있는 스킬 수를 체크
for (int j = 0; j < cnt; j++) {
for (int l = 0; l < K; l++) {
if (quests[i][l] == selected[j]) check++;
}
}
// check가 K와 같다면 클리한 것이므로 클리어 수 증가
if (check >= K) clear++;
}
answer = Math.max(answer, clear);
return;
}
selected[cnt] = cur;
recur(cur + 1, cnt + 1);
recur(cur + 1, cnt);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
// 키, 퀘스트, 스킬 개수 정보 입력
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
M = Integer.parseInt(st.nextToken());
K = Integer.parseInt(st.nextToken());
// 퀘스트 스킬 정보 입력
quests = new int[M][K];
for (int i = 0; i < M; i++) {
st = new StringTokenizer(br.readLine());
for (int j = 0; j < K; j++) {
quests[i][j] = Integer.parseInt(st.nextToken());
}
}
selected = new int[2 * N];
recur(1, 0);
bw.write(String.valueOf(answer));
bw.flush();
bw.close();
br.close();
}
}
알고리즘 문제) BOJ 20950. 미술가 미미
문제 요약
- RGB 표기하기
- 혼합할 모든 물건의 R값끼리 더하고 개수로 나눈다.
- G. B도 똑같이 구함
- 곰두리색의 RGB가 구해졌을 때 RGB 차이가 가장 적은 차이값 출력하기
- 차이값 : abs(Ri-Rj) + abs(Gi-Gj) + abs(Bi-Bj)
- 단, 최대 7개까지만 섞을 수 있고, 1개만으로 사용 할 수도 없음
시간 제한
- 1초
입력
- 물감 개수 N
- 2≤N≤30
- N개의 줄에 물감의 RGB 값
- 곰두리색의 RGB
- 0≤R,G,B≤255
출력
- 곰두리색과 RGB차이가 가장 적은 값 차이값 출력
접근법
- 물감을 2~7개를 섞었을 때의 경우들을 살펴본다
- 그때 곰두리 색의 차이가 가장 적은 경우로 차이값을 갱신한다.
코드
import java.io.*;
import java.util.StringTokenizer;
public class Main {
static int N; // 물감 개수
static int[][] colors; // 물감들의 RGB 정보
static int[] gomduri; // 곰두리 색의 RGB 정보
static int answer = Integer.MAX_VALUE; // 차이값
static void recur(int cur, int cnt, int r, int g, int b) {
if (cnt > 7) return; // 개수가 7개를 넘어가는 순간 pass
if (cur == N) {
// 선택한 개수가 1개 이하 또는 8개 이상일 경우 pass
if (cnt < 2) {
return;
}
// 곰두리색과의 차이값 갱신
answer = Math.min(answer
, Math.abs(gomduri[0] - r / cnt) + Math.abs(gomduri[1] - g / cnt) + Math.abs(gomduri[2] - b / cnt));
return;
}
// 색상을 선택한 경우
recur(cur + 1, cnt + 1
, r + colors[cur][0], g + colors[cur][1], b + colors[cur][2]);
// 색상을 선택하지 않은 경우
recur(cur + 1, cnt, r, g, b);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
N = Integer.parseInt(br.readLine()); // 물감 개수 입력 받기
// 물감 RGB 정보 입력 받기
colors = new int[N][3];
for (int i = 0; i < N; i++) {
st = new StringTokenizer(br.readLine());
colors[i][0] = Integer.parseInt(st.nextToken());
colors[i][1] = Integer.parseInt(st.nextToken());
colors[i][2] = Integer.parseInt(st.nextToken());
}
// 곰두리 색 RGB 정보 입력 받기
gomduri = new int[3];
st = new StringTokenizer(br.readLine());
gomduri[0] = Integer.parseInt(st.nextToken());
gomduri[1] = Integer.parseInt(st.nextToken());
gomduri[2] = Integer.parseInt(st.nextToken());
recur(0, 0, 0, 0, 0);
bw.write(String.valueOf(answer));
bw.flush();
bw.close();
br.close();
}
}
알고리즘 문제) BOJ 19949. 영재의 시험
문제 요약
- 5지선다 객관식 10문제의 시험에서
- 3개의 연속된 문제는 같지 않게 답한다는 규칙을 이용해서 찍었을 때 점수가 5점 이상일 경우의 수 구하기
시간 제한
- 1초
입력
- 시험의 정답이 첫 줄에 주어짐
출력
- 점수가 5점 이상일 경우의 수 출력
접근법
- 완전 탐색으로 생각하기
- 10중 for문 사용해서 정답이 5점이 이상 일 경우 카운트
코드
import java.io.*;
import java.util.StringTokenizer;
public class Main {
static int[] arr; // 문제의 정답
static int[] selected; // 선택한 정답
static int answer; // 정답 개수
static void recur(int cur, int correct) {
// cur : 지금까지 선택한 위치
// correct : 맞은 개수
if (cur == 10) {
// 맞은 개수가 5개 미만이면 pass
if(correct < 5) return;
// 3개 연속인 답이 있는지 체크
boolean check = true;
for (int i = 0; i <= 7; i++) {
if (selected[i] == selected[i + 1] && selected[i] == selected[i + 2]) {
check = false;
break;
}
}
// 조건 충족시 카운팅
if(check) answer++;
return;
}
for (int i = 1; i <= 5; i++) {
selected[cur] = i;
if (arr[cur] == i) {
// 정답이 갖다면 correct + 1
recur(cur + 1, correct + 1);
} else {
// 갖지 않다면 correct
recur(cur + 1, correct);
}
}
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
arr = new int[10];
for (int i = 0; i < 10; i++) {
arr[i] = Integer.parseInt(st.nextToken());
}
selected = new int[10];
recur(0,0);
bw.write(String.valueOf(answer));
bw.flush();
bw.close();
br.close();
}
}
알고리즘 문제) BOJ 14501. 퇴사
문제 요약
- N+1일째 되는 날 퇴사를 하기 위해서, 남은 N일 동안 최대한 많은 상담
- 하루에 하나씩 서로 다른 사람의 상담
- 담을 완료하는데 걸리는 기간 Ti와 상담을 했을 때 받을 수 있는 금액 Pi
시간 제한
- 2초
입력
- N (1 ≤ N ≤ 15)
- N개의 줄에 Ti와 Pi
- 1 ≤ Ti ≤ 5, 1 ≤ Pi ≤ 1,000
출력
- 백준이가 얻을 수 있는 최대 이익
코드
import java.io.*;
import java.util.StringTokenizer;
public class Main {
static int N; // 상담 개수
static int[][] schedules; // 상담 리스트
static int[] selected; // 선택된 스케쥴
static int answer = 0; // 최대 이익
static void recur(int cur, int cnt) {
if (cur == N + 1) {
int nextDay = 0;
int profit = 0;
boolean check = true;
for (int i = 0; i < cnt; i++) {
if (selected[i] < nextDay){
check = false;
break;
}
nextDay = selected[i] + schedules[selected[i]][0];
if (nextDay - 1 > N){
check = false;
break;
}
profit += schedules[selected[i]][1];
}
if(!check) return;
answer = Math.max(answer, profit);
return;
}
// 스케쥴 선택
selected[cnt] = cur;
recur(cur + 1, cnt + 1);
recur(cur + 1, cnt);
}
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st;
// 상담 개수 입력 받기
N = Integer.parseInt(br.readLine());
// 상담 리스트 입력 받기
schedules = new int[N + 1][2];
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
schedules[i][0] = Integer.parseInt(st.nextToken());
schedules[i][1] = Integer.parseInt(st.nextToken());
}
selected = new int[N];
recur(1, 0);
bw.write(String.valueOf(answer));
bw.flush();
bw.close();
br.close();
}
}
'📙 Algorithm Solving > Java' 카테고리의 다른 글
📙[Algo] 24.02.26 알고리즘 (0) | 2024.02.27 |
---|---|
📙[Algo] 24.02.25 알고리즘 (0) | 2024.02.26 |
📙[Algo] 24.02.22 알고리즘 (0) | 2024.02.23 |
📙[Algo] 24.02.21 알고리즘 (0) | 2024.02.22 |
📙[Algo] 24.02.20 알고리즘 (0) | 2024.02.21 |