📖 문제
https://www.acmicpc.net/problem/16938
💡 풀이 방식
• 백트래킹+ 브루트포스
1. 문제들을 배열에 입력받고, 이 배열을 난이도 기준 오름차순 정렬한다.
2. 2~N개까지 캠프에 사용할 문제들을 고른다. (백트래킹)
for(int i = 2 ; i <= N ; i++) {
visited = new boolean[N];
dfs(i, 0);
}
[백트래킹 함수]
- (종료 조건) 목표 갯수만큼 뽑았다면, 문제에서 제시한 2가지 조건을 만족하는지 확인하고 방법 수를 갱신한다.
(여기서 리스트를 오름차순 정렬하지 않는 이유는, 이미 배열을 입력받고 오름차순 정렬해두어서 리스트에 저장할 때 이미 오름차순으로 난이도를 저장해 두기 때문이다.)
if(cnt == target) {
int sum = 0;
List<Integer> list = new ArrayList<>();
for(int i = 0 ; i < N ; i++) {
if(visited[i]) {
list.add(i);
sum += arr[i].lv;
}
}
int diff = arr[list.get(list.size() -1)].lv - arr[list.get(0)].lv; // 가장 어려운 문제와 가장 쉬운 문제 난이도 차
if(sum >= L && sum <= R && (diff >= X)) { // 1, 2번 조건 성립하는지 확인
answer++;
}
return;
}
- i번 문제를 뽑는 반복문
for(int i = cnt ; i < N ; i++) {
if(!visited[i]) {
visited[i] = true;
dfs(target, i + 1);
visited[i] = false;
}
}
💥 유의사항
종료 조건에서 리스트에 문제의 인덱스를 저장하는 것이므로, 가장 어려운 문제와 가장 쉬운 문제의 난이도 차이를 구할 때는 배열에서 해당 인덱스의 난이도 값을 가져와서 계산해야 한다.
int diff = arr[list.get(list.size() -1)].lv - arr[list.get(0)].lv;
🔺 코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
import java.util.*;
import java.io.*;
public class Main {
static int N,L,R,X;
static Node[] arr;
static boolean[] visited;
static int answer = 0;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
N = Integer.parseInt(st.nextToken());
L = Integer.parseInt(st.nextToken()); // 최저
R = Integer.parseInt(st.nextToken()); // 최고
X = Integer.parseInt(st.nextToken()); // 최저 난이도 차
arr = new Node[N];
st = new StringTokenizer(br.readLine(), " ");
for(int i = 0 ; i < N ; i++) {
arr[i] = new Node(i, Integer.parseInt(st.nextToken()));
}
Arrays.sort(arr); // 난이도 기준 오름차순 정렬
// 캠프에 사용할 문제 2개 이상 고르기
for(int i = 2 ; i <= N ; i++) {
visited = new boolean[N];
dfs(i, 0);
}
System.out.println(answer);
}
private static void dfs(int target, int cnt) { // 목표 갯수, 현재 뽑은 갯수
// 목표 갯수만큼 뽑았으면 조건 만족하는지 확인하고 방법 수 갱신
if(cnt == target) {
int sum = 0;
List<Integer> list = new ArrayList<>();
for(int i = 0 ; i < N ; i++) {
if(visited[i]) {
list.add(i);
sum += arr[i].lv;
}
}
int diff = arr[list.get(list.size() -1)].lv - arr[list.get(0)].lv;
if(sum >= L && sum <= R && (diff >= X)) { // 1번 조건과 2번 조건 성립하는지 확인
answer++;
}
return;
}
for(int i = cnt ; i < N ; i++) {
if(!visited[i]) {
visited[i] = true;
dfs(target, i + 1);
visited[i] = false;
}
}
}
}
class Node implements Comparable<Node> {
int idx, lv;
public Node(int idx, int lv) {
this.idx = idx;
this.lv = lv;
}
// 난이도 기준 오름차순 정렬
@Override
public int compareTo(Node n) {
return this.lv - n.lv;
}
}
|
cs |
➕ 다른 풀이 방식
- dfs 메소드의 파라미터에 최대 최소 난이도를 저장해 들고 다니며 조건을 만족하는지 확인하도록 푸셨다.
[백준] code.plus(브루트 포스 Part 1,JAVA)16938번, 캠프 준비
문제 링크 16938번: 캠프 준비 난이도가 10, 30인 문제를 고르거나, 20, 30인 문제를 고르면 된다. www.acmicpc.net 주의사항 JAVA를 사용하여 프로그램을 사용하였습니다. 백준에서 코드를 작성하였을 때
tussle.tistory.com
- 나처럼 리스트를 만들지 않고, 최대 난이도와 최소 난이도 값을 저장하는 변수만 만들어 활용하셨따. 그리고 dfs 함수 부분도 조금 다르심
백준 16938번 캠프 준비 (JAVA)
https://www.acmicpc.net/problem/16938 16938번: 캠프 준비 난이도가 10, 30인 문제를 고르거나, 20, 30인 문제를 고르면 된다. www.acmicpc.net 저는 해당 문제를 조합을 이용하여 각각의 시험을 사용하는 것과 안하
bacchus-lover.tistory.com
- 엄청 간단한 풀이 ㄴㅇㄱ
백준 16938번 : 캠프 준비(Java)
https://www.acmicpc.net/problem/16938 16938번: 캠프 준비 난이도가 10, 30인 문제를 고르거나, 20, 30인 문제를 고르면 된다. www.acmicpc.net [풀이] 조합론, 그리고 브루트포스 유형의 문제입니다. 캠프에 사용할
today-retrospect.tistory.com
💦 어려웠던 점
- 푸는 데 17분, 디버깅 13분,,
- 내가 조금 복잡하게 푼 것 같다,,,
1회독 | 2회독 | 3회독 | 4회독 | 5회독 |
V | 240530 |
(+240530 2회독 : 23332KB, 200ms)
20분 소요...
20줄 정도 더 줄였다!
객체 안 만들고 그냥 배열 자체를 정렬했다. (문제 순서는 상관없길래,,,)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
|
import java.util.*;
import java.io.*;
public class Main {
static int N,L,R,X, answer;
static int[] A;
static boolean[] chk;
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
StringTokenizer st = new StringTokenizer(br.readLine(), " ");
N = Integer.parseInt(st.nextToken());
L = Integer.parseInt(st.nextToken());
R = Integer.parseInt(st.nextToken());
X = Integer.parseInt(st.nextToken());
A = new int[N];
st = new StringTokenizer(br.readLine(), " ");
for(int i = 0 ; i < N ; i++) {
A[i] = Integer.parseInt(st.nextToken());
}
Arrays.sort(A); // 미리 오름차순 정렬해두기
for(int i = 2 ; i <= N ; i++) { // 문제 2~N개 뽑기
chk = new boolean[N];
dfs(0, i);
}
System.out.println(answer);
}
private static void dfs(int cnt, int target) {
if(cnt == target) {
List<Integer> list = new ArrayList<>(); // 뽑은 숫자 저장 리스트
int sum = 0; // 뽑은 숫자들의 합
for(int i = 0 ; i < N ; i++) {
if(chk[i]) { // 뽑은 숫자인 경우 > 리스트에 숫자를 저장하고, 합 갱신
list.add(A[i]);
sum += A[i];
}
}
// L 이상 R 이하고, 리스트의 최대-최소 값이 X 이상인 경우 정답 갯수+1
if(L <= sum && sum <= R && (list.get(list.size()-1) - list.get(0) >= X)) {
answer++;
}
return;
}
for(int i = cnt ; i < N ; i++) {
if(!chk[i]) {
chk[i] = true;
dfs(i + 1, target);
chk[i] = false;
}
}
}
}
|
cs |
'코테 > 백준' 카테고리의 다른 글
[백준/JAVA] 16956번: 늑대와 양 (0) | 2024.05.06 |
---|---|
[백준/JAVA] 9944번: NxM 보드 완주하기 (0) | 2024.05.05 |
[백준/JAVA] 3019번: 테트리스 (0) | 2024.04.30 |
[백준/JAVA] 16509번: 장군 (0) | 2024.04.30 |
[백준/JAVA] 15683번: 감시 (0) | 2024.04.30 |