ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 1759 암호 만들기(자바)
    백준/브루트 포스 2022. 2. 3. 22:31

     

     

     

     

     

    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    import java.util.Arrays;
    import java.util.StringTokenizer;
    
    
    public class Main {
    	
    	static int N;
    	static int M;
    	static String input[];
    	static boolean check[];
    	static String word;
    	static StringBuilder result;
    	
    	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());
    		M = Integer.parseInt(st.nextToken());
    		check = new boolean [M];
    		result = new StringBuilder();
    	
    		input = new String[M];
    		StringTokenizer st1 = new StringTokenizer(br.readLine(), " ");	
    	
    		for(int i=0;i<M; i++) {
    			input[i] = (String) st1.nextToken();
    		}
    	
    		Arrays.sort(input);
    	
    		dfs(0, 0);
    	
    	}	
    	
    	public static void dfs(int start, int depth) {
    		
    		if(depth==N) {
    		
    			for(int i=0; i<M;i++) {
    			if(check[i]) {
    				result.append(input[i]);
    			
    		    	}
    			}
    			
    			word = result.toString();
    			result.setLength(0);
    			
    			int count = 0;
    			
    			if(word.contains("a")) count++;
    			if(word.contains("o")) count++;
    			if(word.contains("u")) count++;
    			if(word.contains("e")) count++;
    			if(word.contains("i")) count++;
    			
    			if(1 <= count && count <= N-2) {
    				
    					System.out.println(word);
    				
    			}
    		}
    		
    		
    		for(int i =start; i<M;i++) {
    			
    			check[i]=true;
    			dfs(i+1, depth+1);
    			
    			check[i]=false;
    		}
    	}
    }

     

    이전에 풀었던 로또문제(백준 6603) 이랑 비슷해서 비교적 수월하게 풀었다.

     

    https://happy-fun.tistory.com/196?category=981765 

     

    6603 로또 (java)

    import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.StringTokenizer; public class Main { static int number[]; static boolean result[]; stati..

    happy-fun.tistory.com

     

     

     

    dfs 를 이용해서 완성했다.

    코드를 설명해보겠다.

     

    N : 암호 길이 // 4

    M : 입력 받은 문자 개수 //6

    input 배열 : 입력 받은 문자를 input 배열에 넣음. 그리고나서 배열을 오름차순 정렬하기 때문에

    최종적으로 input 배열에는 

    a c i s t w 순으로 저장된다.

     

    check 배열과 result 변수는 아래에서 설명하겠다.

     

    ---------------------------------

     

    dfs 메서드를 살펴보자.

    우리는 dfs(0,0) 부터 시작한다.

    그럼 일단 아래 부분부터 살펴보자.

    	for(int i =start; i<M;i++) {
    			
    			check[i]=true;
    			dfs(i+1, depth+1);
    			
    			check[i]=false;
    		}

     

     

    dfs(0,0) 이므로, 

    start = 0, depth =0 이다.

    그리고 check 배열에 설명하자면

    타입이 boolean 으로

    처음에는 모든 값이 false 로 초기화 되어 있다.

    하지만 위에서 보듯이 check 배열의 값을 true 로 바꿔주고 있다.

     

    이를 설명해보겠다.

     

    input 배열에는 다음과 같이 저장되어 있다.

    a c i s t w 

     

    만약 check 배열의 값들이 true true false false true true 로 되었다고 하자.

    이때 우리는 true 의 값을 가지고 있는 인덱스, 즉 여기서는 0,1,4,5 에 해당하는

    input 배열의 값을 찾아서,

    즉 a c t w 

    출력할 것이다.

     

    이게 가능하도록 아래 코드 완성

     

    	if(depth==N) {
    		
    			for(int i=0; i<M;i++) {
    			if(check[i]) {
    				result.append(input[i]);
    			
    		    	}
    			}
    			
    			word = result.toString();
    			result.setLength(0);
    			
    			int count = 0;
    			
    			if(word.contains("a")) count++;
    			if(word.contains("o")) count++;
    			if(word.contains("u")) count++;
    			if(word.contains("e")) count++;
    			if(word.contains("i")) count++;
    			
    			if(1 <= count && count <= N-2) {
    				
    					System.out.println(word);
    				
    			}
    		}

     

     

    depth==N, 즉 여기서는 4를 만족하게 되면

    check 배열의 true 값이 4개가 된다.

    이때 check 배열의 인덱스에 해당하는 input 배열의 글자를 출력해서

    길이가 4인 암호를 출력한다.

     

    예를들어,

    아래와 같다.

    input 배열은 a c i s t w 이고,

    그 아래 check 배열의 상태, 그 인덱스에 해당되는 input 배열의 글자이다.

     

     

     

    이와 더불어 모음이 1글자 이상, 자음이 2글자 이상인 조건을 만족하는 글자를 최종적으로 출력하게 한 것이다.

     

    그리고 여기서 보면, StringBuilder 타입의 result 변수에 글자들을 추가한 다음

    String 타입의 word 에 옮겨 담아서 출력하는 것을 알 수 있다.

     

    이는, StringBuilder 의 append 메서드를 사용하기 위함이다.

    String 타입에서는 글자에 다른 글자를 추가할 때 concat 라는 메서드를 사용하는데,

    이 메서드는 2개의 글자를 합쳐서 출력해줄 뿐, A 단어에 B 단어를 붙여서 유지해주지 않는 듯 했다.

    그래서 StringBuilder 를 이용해서 글자들을 이어붙이고 다시 String 타입의 word 변수에 옮겨 담았다.

     

     

    더불어서 

    	result.setLength(0);

    이 코드로 result 변수를 초기화 한 뒤, 

    새로운 단어를 담도록 했다.

     

     

     

    이 사진에서도 볼 수 있지만,

    맨 처음에는 t t t t f f 이지만

    그 아래는 t t t f t f 이다.

     

    즉, 인덱스 3의 위치 t 값이 그 다음에는 f 로 변해있는데,

    	for(int i =start; i<M;i++) {
    			
    			check[i]=true;
    			dfs(i+1, depth+1);
    			
    			check[i]=false;
    		}

    이 코드에서 보이듯이, dfs() 메서드를 마치고 돌아와서는 다시 false 로 바꾸기 때문이다.

     

     

    '백준 > 브루트 포스' 카테고리의 다른 글

    14500 테트로미노  (0) 2022.04.24
    2501 약수 구하기(자바)  (0) 2022.02.19
    1065 한수  (0) 2022.02.08
    2798 블랙잭  (0) 2021.10.18

    댓글

Designed by Tistory.