[백준] 16938번 캠프 준비 - Java

JeongYong·2023년 1월 20일
0

Algorithm

목록 보기
97/275

문제 링크

https://www.acmicpc.net/problem/16938

문제

알고리즘 캠프를 열려면 많은 준비가 필요하다. 그 중 가장 중요한 것은 문제이다. 오늘은 백준이를 도와 알고리즘 캠프에 사용할 문제를 고르려고 한다.

백준이는 문제를 N개 가지고 있고, 모든 문제의 난이도를 정수로 수치화했다. i번째 문제의 난이도는 Ai이다.

캠프에 사용할 문제는 두 문제 이상이어야 한다. 문제가 너무 어려우면 학생들이 멘붕에 빠지고, 문제가 너무 쉬우면 학생들이 실망에 빠지게 된다. 따라서, 문제 난이도의 합은 L보다 크거나 같고, R보다 작거나 같아야 한다. 또, 다양한 문제를 경험해보기 위해 가장 어려운 문제와 가장 쉬운 문제의 난이도 차이는 X보다 크거나 같아야 한다.

캠프에 사용할 문제를 고르는 방법의 수를 구해보자.

입력

첫째 줄에 N, L, R, X가 주어진다.

둘째 줄에는 문제의 난이도 A1, A2, ..., AN이 주어진다.

출력

캠프에 사용할 문제를 고르는 방법의 수를 출력한다.

제한

  • 1 ≤ N ≤ 15
  • 1 ≤ L ≤ R ≤ 109
  • 1 ≤ X ≤ 106
  • 1 ≤ Ai ≤ 106

알고리즘: 브루트포스 알고리즘, 비트마스킹, 백트래킹

풀이

모든 경우의 수를 구해서 L <= sum <= R && (max - min) >= X 이 조건에 맞으면 count 해준다.

알고리즘 캠프에 사용할 문제는 2개 이상이어야 하므로 2~N 길이의 조합을 모두 구해야 함 -> (중복 없이, 순서 상관 x)

시간 복잡도는 (전체 문제 수! / 고른 문제 수! * (전체 문제 수 - 고른 문제 수)!) 이 조합 공식을 이용해보면 TLE 없이 통과할 수 있는 횟수임.

소스 코드

import java.io.*;
import java.util.*;

public class Main {
    static int N;
    static long L, R, X;
    static long A[];
    static Stack<Long> result = new Stack<>();
    static int ans = 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 = Long.parseLong(st.nextToken());
        R = Long.parseLong(st.nextToken());
        X = Long.parseLong(st.nextToken());
        A = new long[N];
        StringTokenizer n_st = new StringTokenizer(br.readLine());
        for(int i=0; i<N; i++) {
            A[i] = Long.parseLong(n_st.nextToken());
        }
        for(int i=2; i<=N; i++) {
            DFS(0, i);
        }
        System.out.println(ans);
    }
    
    static void DFS(int ind, int len) {
        if(result.size() == len) {
            long sum = 0;
            long min = 1000001;
            long max = -1;
            for(int i=0; i<len; i++) {
                sum += result.get(i);
                min = Math.min(min, result.get(i));
                max = Math.max(max, result.get(i));
            }
            if((L <= sum && sum <= R) && ((max - min) >= X)) ans += 1;
            return;
        }
        for(int i=ind; i<A.length; i++) {
            result.push(A[i]);
            DFS(i+1, len);
            result.pop();
        }
    }
}

0개의 댓글