Algorithm/백준

[BOJ] 2798: 블랙잭(JAVA)

류진주 2021. 9. 9. 18:29

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

 

2798번: 블랙잭

첫째 줄에 카드의 개수 N(3 ≤ N ≤ 100)과 M(10 ≤ M ≤ 300,000)이 주어진다. 둘째 줄에는 카드에 쓰여 있는 수가 주어지며, 이 값은 100,000을 넘지 않는 양의 정수이다. 합이 M을 넘지 않는 카드 3장

www.acmicpc.net

문제

카지노에서 제일 인기 있는 게임 블랙잭의 규칙은 상당히 쉽다. 카드의 합이 21을 넘지 않는 한도 내에서, 카드의 합을 최대한 크게 만드는 게임이다. 블랙잭은 카지노마다 다양한 규정이 있다.

한국 최고의 블랙잭 고수 김정인은 새로운 블랙잭 규칙을 만들어 상근, 창영이와 게임하려고 한다.

김정인 버전의 블랙잭에서 각 카드에는 양의 정수가 쓰여 있다. 그 다음, 딜러는 N장의 카드를 모두 숫자가 보이도록 바닥에 놓는다. 그런 후에 딜러는 숫자 M을 크게 외친다.

이제 플레이어는 제한된 시간 안에 N장의 카드 중에서 3장의 카드를 골라야 한다. 블랙잭 변형 게임이기 때문에, 플레이어가 고른 카드의 합은 M을 넘지 않으면서 M과 최대한 가깝게 만들어야 한다.

N장의 카드에 써져 있는 숫자가 주어졌을 때, M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 구해 출력하시오.

입력

첫째 줄에 카드의 개수 N(3 ≤ N ≤ 100)과 M(10 ≤ M ≤ 300,000)이 주어진다. 둘째 줄에는 카드에 쓰여 있는 수가 주어지며, 이 값은 100,000을 넘지 않는 양의 정수이다.

합이 M을 넘지 않는 카드 3장을 찾을 수 있는 경우만 입력으로 주어진다.

출력

첫째 줄에 M을 넘지 않으면서 M에 최대한 가까운 카드 3장의 합을 출력한다.

예제 입력 1 복사

5 21

5 6 7 8 9

예제 출력 1 복사

21

예제 입력 2 복사

10 500

93 181 245 214 315 36 185 138 216 295

예제 출력 2 복사

497

 


[문제 풀이]

조합을 이용하여 문제를 해결하였다. 세 카드의 합이 입력받은 변수 M보다 같거나 작아야하며, 그러한 합 중 가장 큰 값을 반환하여야 하는 문제이다. 따라서 카드들 중에서 순서에 상관없이 카드 3개를 뽑는 조합을 이용하였다. 

카드 3개를 뽑아 그 합을 구하고, 그 합들 중 M보다 작거나 같으면서 가장 큰 합을 선택하는 com함수를 구현하였다.

com함수의 start는 시작 인덱스이며, 순서를 고려하지 않는 조합을 찾는 것이므로 start~N 전까지의 카드 중에서 3가지 카드를 선택한다. 

 

1. card 배열은 카드에 쓰여있는 수가 저장되어있는 정수 배열

2. v 배열은 해당 카드를 선택했는지 여부를 가리킬 boolean 배열

3. max는 카드 3개의 합 중 M보다 작거나 같은 것 중 가장 큰 값

4. start는 카드 선택 index

5. sum은 선택한 카드의 합

6. k는 선택한 카드 개수

 

com 함수는 다음과 같이 진행된다.

1. sum이 M보다 크다면 조건을 만족하지 않는 것이므로 return

2. k>=3인 경우는 카드 3개를 뽑은 경우이므로 sum값과 max 값을 비교하여 sum 값이 max보다 크다면 max값을 sum값으로 변경한다.

3. k<3인 경우는 k가 3이 되거나 sum이 M보다 커질 때까지 다음 과정을 진행한다.

    3-1. i번째 카드를 가리키는 변수이다. 만약 i카드를 아직 선택하지 않았으면, v[i] 는 false일 것이다. 따라서 해당 카드를 선택하고 v[i]=true로 변경, 카드 하나를 선택한 것이므로 선택한 카드 개수인 k를 1 증가, sum에 선택한 카드에 적혀있는 수인 card[i]를 더해준다.

    3-2. com(i,sum,k)를 다시 진행

    3-3. 조건에 걸려 return되면, sum-=card[i], k-=1, v[i]=false로 바꾸고 다시 for문을 진행

4. 모든 조합에 대해 max를 찾았으면, 해당 값을 출력하고 종료한다.

 

 

[코드]

import java.util.*;

public class Main {
    static int[] card;
    static int M; 
    static  boolean[] v ;
    static int max = 0;
    static int N;
    public static void com(int start, int sum, int k) {
        if(sum>M) 
            return;

        if(k>=3) {
            if(max<sum&&sum<=M) 
                max=sum;

            return;

        }
        for(int i=start;i<N;i++) {
            if(!v[i]) {
                v[i]=true;
                sum+=card[i];
                k+=1;
                com(i,sum,k);
                v[i]=false;
                sum-=card[i];
                k-=1;
            }
        }

    }
    public static void main(String[] args) {
    
      Scanner sc = new Scanner(System.in);
     
      
      N = sc.nextInt();
      M = sc.nextInt();
      card = new int[M];
      v = new boolean[M];
      
      for(int i=0;i<N;i++) {
           card[i] = sc.nextInt();
      }
      
      for(int i=0;i<N;i++) {
           com(i,0,0);
      }
      
      System.out.println(max);
   }
}

'Algorithm > 백준' 카테고리의 다른 글

[BOJ] 1927: 최소 힙(JAVA)  (0) 2021.09.10
[BOJ] 11279: 최대 힙(JAVA)  (0) 2021.09.10
[BOJ] 1436: 영화감독 숌(JAVA)  (0) 2021.09.09
[BOJ] 11653: 소인수분해(JAVA)  (0) 2021.09.05
[BOJ] 1966: 프린터 큐(JAVA)  (0) 2021.09.05