[백준 2503] 숫자 야구(Java)

최민길(Gale)·2023년 1월 4일
1

알고리즘

목록 보기
1/172

문제 링크 : https://www.acmicpc.net/problem/2503

이 문제는 주어진 N의 크기가 크지 않고, 반복문을 도는 횟수도 많지 않아 완전탐색으로 충분히 풀 수 있는 문제입니다.

문제의 핵심 풀이는 다음과 같습니다. 답으로 예상되는 모든 숫자들을 입력받은 숫자들과 비교하여 얻은 스트라이크와 볼의 값이 입력받은 스트라이크와 볼의 값과 같다면 비교한 숫자는 정답일 가능성이 있으므로 계속 살리고, 다른 경우는 탐색 범위에서 제외시켜 더 빠르게 탐색하는 것이 목표입니다.

이 때 정답 가능성이 있는 수와 입력받은 수가 3자리 이므로 각각 반복문을 돌려 자리수와 값을 비교하여 만약 자리수와 값이 모두 같다면 스트라이크를, 자리수는 다른데 값이 같다면 볼을 1씩 증가시켜 스트라이크와 볼을 계산합니다.

다음은 실제 코드입니다.

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

public class Main{
    static int N;
    static boolean[] check = new boolean[1000];

    public static void main(String[] args) throws Exception{
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        StringTokenizer st = new StringTokenizer(br.readLine());
        N = Integer.parseInt(st.nextToken());

        // 가능한 정답의 경우 check 배열을 true로, 가능하지 않은 경우 false로 설정
        for(int i=123;i<1000;i++){
            String str = Integer.toString(i);

            // 문제에 따르면 숫자 내부에 0이 있을 경우는 정답으로 가능하지 않으므로 제외
            if(str.charAt(0)=='0' || str.charAt(1)=='0' || str.charAt(2)=='0') continue;

            // 문제에 따르면 모든 자릿수의 숫자가 달라야 하기 때문에 같은 숫자가 있을 경우 제외
            if(str.charAt(0)==str.charAt(1) || str.charAt(0)==str.charAt(2) || str.charAt(1)==str.charAt(2)) continue;
            check[i] = true;
        }

        for(int i=0;i<N;i++){
            // 입력받은 값과 정답과의 스트라이크와 볼 값
            st = new StringTokenizer(br.readLine());
            int req = Integer.parseInt(st.nextToken());
            int s = Integer.parseInt(st.nextToken());
            int b = Integer.parseInt(st.nextToken());

            // 예상 가능한 모든 정답을 탐색
            for(int ans=123;ans<1000;ans++){
                // 만약 정답 가능성이 있는 수라면
                if(check[ans]){
                    int ns = 0;
                    int nb = 0;

                    // 정답 가능성이 있는 수와 입력받은 수와 스트라이크와 볼 비교
                    // 이 때 입력받은 수, 정답 가능성이 있는 수 각각을 반복문을 돌려 각 자리수와 값을 비교
                    for(int first=0;first<3;first++){
                        char req_split = Integer.toString(req).charAt(first);

                        for(int second=0;second<3;second++){
                            char ans_split = Integer.toString(ans).charAt(second);

                            // 자리수도 같고 값도 같다면 스트라이크
                            // 자리수는 다른데 값은 같다면 볼
                            if(req_split == ans_split && first == second) ns++;
                            else if(req_split == ans_split && first != second) nb++;
                        }
                    }

                    // 입력받은 스트라이크, 볼 값과 계산한 값이 같다면 정답 가능성이 있는 수
                    if(ns == s && nb == b) check[ans] = true;
                    // 아니라면 제외
                    else check[ans] = false;
                }
            }
        }

        // 정답 가능성이 있는 수를 세서 카운트 및 출력
        int ans = 0;
        for(int i=123;i<1000;i++){
            if(check[i]) ans++;
        }

        System.out.println(ans);
    }
}

profile
저는 상황에 맞는 최적의 솔루션을 깊고 정확한 개념의 이해를 통한 다양한 방식으로 해결해오면서 지난 3년 동안 신규 서비스를 20만 회원 서비스로 성장시킨 Software Developer 최민길입니다.

0개의 댓글