ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • BOJ) 가르침 (1062 번)
    알고리즘/백준 2021. 2. 18. 11:40
    반응형

    가르침

     

    1062번: 가르침

    첫째 줄에 단어의 개수 N과 K가 주어진다. N은 50보다 작거나 같은 자연수이고, K는 26보다 작거나 같은 자연수 또는 0이다. 둘째 줄부터 N개의 줄에 남극 언어의 단어가 주어진다. 단어는 영어 소문

    www.acmicpc.net

    모든 단어는 "anta"로 시작되고, "tica"로 끝난다. 남극언어에 단어는 N개 밖에 없다.

    어떤 K개의 글자를 가르쳐야 학생들이 읽을 수 있는 단어의 개수가 최대가 되는지 구하는 문제다.

     

    단어는 모두 소문자로 주어지고,  1 <= N <= 50,  0 <= K <= 26 , 8 <= 모든 단어의 길이 <= 15 라는 조건이 주어졌다.

     

    알고리즘 분류가 브루트포스, 비트 마스킹,  백트래킹으로 되어있다.

    위의 알고리즘들을 이용해서 이 문제를 풀었다.

     

    우선, 모든 단어의 시작 prefix와 끝인 suffix에 5 글자가 존재하기 때문에 k를 입력받을 때, 미리 -5를 해주었다. (anta, tica ~> a, c, i, n, t)

    그리고, overflow를 방지하기 위해 boolean 배열인 check를 위의 다섯 글자를 가지고 초기화해주었다.

    사실, 이 부분도 비트마스크로 해결할 수는 있지만, 조금 더 직관적이길 바래서 boolean을 택했다.

    또한, 가르쳐줄 글자 a ~ z의 값을 0 ~ 26으로 정해두고 비트마스크를 설정해주었다.

    default인 다섯 글자를 먼저 생성해주고, 나머지 k-5 개의 순열을 구해주었다.

     

    순열을 구할 때는 a~z인 0~26을 돌면서 이미 bitmask에 들어있는지 확인하고, 비트 마스킹이 안돼있으면 새롭게 추가하면서 재귀적으로 탐색하게 만들어 주었다. 탐색이 끝난 후, 돌아왔을 때는 다른 순열에서 이 값이 포함되어 있으면 안되기 때문에 false로 바꿔주어 백트래킹 설정을 해줬다.

    이 재귀 메소드를 돌면서 k-5개 만큼 추가해주었으면, 몇 개의 단어가 비트마스크 글자로 읽을 수 있는지 값을 구해주었다.

     

    처음 단어를 저장할 때부터 비트마스크로 저장해두어서 연산 횟수를 줄여주었다.

    이 비트마스크 단어 배열을 돌면서, 위에서 구한 비트마스크와 AND 연산 (&)을 통해 해당 단어를 읽을 수 있는지 판별해주어 MAX 값을 최신화 해줬다.

     

    이 문제를 계기로 비트마스크가 어렵지 않다고 느껴졌는데, 어떤 문제에 비트마스크를 적용해야하는지 조금 더 문제를 풀면서 감을 찾아야겠다.

     

    코드

     

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.StringTokenizer;
    
    public class Teaching_1062 {
      static final int ASCII_DEFAULT = 97, ALPHABET_LENGTH = 26;
    
      static int answer;
      static int[] words;
    
      public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int n = Integer.parseInt(st.nextToken());
        int m = Integer.parseInt(st.nextToken()) -5; // prefix, suffix 기본 5개 a c i n t
        words = new int[n];
    
        for(int i=0; i<n; i++) {
          String inputWord = br.readLine();
          int len = inputWord.length();
          for(int j = 0; j<len; j++) {
            words[i] |= (1 << (inputWord.charAt(j) - ASCII_DEFAULT));
          }
        }
    
        br.close();
        solution(m);
      }
    
      private static void solution(int m) {
        if(m>=0) {
          final int[] DEFAULT_ALPHABETS = {0,2,8,13,19}; // a, c, i, n, t
          boolean[] check = initCheck(DEFAULT_ALPHABETS);
          int bitMask = 0;
          for(int idx : DEFAULT_ALPHABETS) {
            bitMask |= (1 << idx);
          }
          permutation(1, m, bitMask, check);
        }
        System.out.println(answer);
      }
    
      private static boolean[] initCheck(int[] DEFAULT_ALPHABET) {
        boolean[] check = new boolean[ALPHABET_LENGTH];
        for(int idx : DEFAULT_ALPHABET) {
          check[idx] = true;
        }
        return check;
      }
    
      private static void permutation(int index, int count, int bitMask, boolean[] check) {
        if(count == 0) {
          // 검증
          findMax(bitMask);
          return;
        }
        if(index == ALPHABET_LENGTH) { // out of index
          return;
        }
        if(!check[index]) { // 새로 추가하는 경우
          check[index] = true;
          permutation(index+1, count-1, bitMask | (1 << index), check);
          check[index] = false;
        }
        permutation(index+1, count, bitMask, check); // 추가 없이 다음으로
      }
    
      private static void findMax(int bitMask) {
        int count =0;
        for(int target : words) {
          if(target == (target & bitMask)) {
            count++;
          }
        }
    
        answer = Math.max(count, answer);
      }
    }
    
    반응형

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

    BOJ) 자두나무 (2240 번)  (0) 2021.02.23
    BOJ) 수들의 합 2 (2003 번)  (0) 2021.02.18
    BOJ) 순열 사이클 (10451번)  (0) 2021.02.15
    BOJ) 앱 (7579 번)  (0) 2021.02.15
    BOJ) 다리 만들기  (0) 2021.02.14

    댓글

Designed by Tistory.