갓생살기프로젝트

[백준/BOJ/C++] 2503번 숫자야구 - 완전탐색 본문

차근차근 알고리즘/etc.

[백준/BOJ/C++] 2503번 숫자야구 - 완전탐색

Heeyeon.dev 2021. 1. 29. 17:17
728x90

 

2503번: 숫자 야구

첫째 줄에는 민혁이가 영수에게 몇 번이나 질문을 했는지를 나타내는 1 이상 100 이하의 자연수 N이 주어진다. 이어지는 N개의 줄에는 각 줄마다 민혁이가 질문한 세 자리 수와 영수가 답한 스트

www.acmicpc.net

1. 문제

정보문화진흥원 정보 영재 동아리에서 동아리 활동을 하던 영수와 민혁이는 쉬는 시간을 틈타 숫자야구 게임을 하기로 했다.

  • 영수는 1에서 9까지의 서로 다른 숫자 세 개로 구성된 세 자리 수를 마음속으로 생각한다. (예: 324)
  • 민혁이는 1에서 9까지의 서로 다른 숫자 세 개로 구성된 세 자리 수를 영수에게 묻는다. (예: 123)
  • 민혁이가 말한 세 자리 수에 있는 숫자들 중 하나가 영수의 세 자리 수의 동일한 자리에 위치하면 스트라이크 한 번으로 센다. 숫자가 영수의 세 자리 수에 있긴 하나 다른 자리에 위치하면 볼 한 번으로 센다.

예) 영수가 324를 갖고 있으면 

  • 429는 1 스트라이크 1 볼이다.
  • 241은 0 스트라이크 2 볼이다.
  • 924는 2 스트라이크 0 볼이다.
  • 영수는 민혁이가 말한 수가 몇 스트라이크 몇 볼인지를 답해준다.
  • 민혁이가 영수의 세 자리 수를 정확하게 맞추어 3 스트라이크가 되면 게임이 끝난다. 아니라면 민혁이는 새로운 수를 생각해 다시 영수에게 묻는다.

현재 민혁이와 영수는 게임을 하고 있는 도중에 있다. 민혁이가 영수에게 어떤 수들을 물어보았는지, 그리고 각각의 물음에 영수가 어떤 대답을 했는지가 입력으로 주어진다. 이 입력을 바탕으로 여러분은 영수가 생각하고 있을 가능성이 있는 수가 총 몇 개인지를 알아맞혀야 한다.

아래와 같은 경우를 생각해보자.  

  • 민혁: 123
  • 영수: 1 스트라이크 1 볼.
  • 민혁: 356
  • 영수: 1 스트라이크 0 볼.
  • 민혁: 327
  • 영수: 2 스트라이크 0 볼.
  • 민혁: 489
  • 영수: 0 스트라이크 1 볼.

이때 가능한 답은 324와 328, 이렇게 두 가지이다.

영수는 동아리의 규율을 잘 따르는 착한 아이라 민혁이의 물음에 곧이곧대로 정직하게 답한다. 그러므로 영수의 답들에는 모순이 없다.

민혁이의 물음들과 각각의 물음에 대한 영수의 답이 입력으로 주어질 때 영수가 생각하고 있을 가능성이 있는 답의 총 개수를 출력하는 프로그램을 작성하시오.


2. 입력

첫째 줄에는 민혁이가 영수에게 몇 번이나 질문을 했는지를 나타내는 1 이상 100 이하의 자연수 N이 주어진다. 이어지는 N개의 줄에는 각 줄마다 민혁이가 질문한 세 자리 수와 영수가 답한 스트라이크 개수를 나타내는 정수와 볼의 개수를 나타내는 정수, 이렇게 총 세 개의 정수가 빈칸을 사이에 두고 주어진다.


3. 출력

첫 줄에 영수가 생각하고 있을 가능성이 있는 답의 총 개수를 출력한다.


4. 풀이

숫자 야구 문제는 입력되는 정보를 가지고 수의 조합을 예측하는 방법으로는 풀 수 없다.

이 문제는 완전탐색으로 풀어야 하는데, 답의 범위가 123부터 987까지이기 때문에 모든 경우를 검사하여 확인하는것이 가능하다.

먼저 입력받는 숫자와 그 숫자의 strike, ball 갯수의 정보를 저장하기 위해 num구조체를 만들고, num 구조체 배열을 입력받은 N만큼 동적 할당 해준다.

하단 코드를 보면 num 구조체에 first, second, third 변수가 있는데, 이는 각 자리별로 검사를 용이하게 하기 위함이다.

입력을 모두 받은 다음에는 123부터 987까지 반복하며 해당 숫자와 입력받은 모든 숫자들의 ball과 strike 갯수가 일치하는지 검사한다. 갯수가 일치한다면 N_count를 올려주고, 입력받은 케이스에대해 모든 비교가 끝나면 현재 N_count가 N과 일치하는지 확인한다. N과 일치한다면 그 숫자는 정답이 될 수 있는 숫자이기 때문에 answer++을 해준다.


5. 소스코드

#include <iostream>
using namespace std;
struct num{
    int question; //민혁이가 불러주는 숫자
    int strike; 
    int ball;
    int first; //백의 자리
    int second; //십의 자리
    int third; //일의 자리
};

int main(){
    int N; 
    int answer = 0;
    cin>>N;
    struct num *array = new num[N];
    int question, strike, ball;
    for(int i = 0; i < N; i++){
        cin>>question;
        cin>>strike;
        cin>>ball;
        array[i].question = question;
        array[i].strike = strike;
        array[i].ball = ball;
        array[i].first = question/100;
        array[i].second = (question%100 - question%10)/10;
        array[i].third = question%10;
    }

    int first, second, third;
    int strike_count = 0;
    int ball_count = 0;
    int N_count = 0;

    for(int i = 123; i <= 987; i++){
        strike_count = 0;
        ball_count = 0;
        N_count = 0;
        first = i/100;
        second = (i%100 - i%10)/10;
        third = i%10;
        //각 자리의 숫자가 0이 아니면서 다른 자리의 숫자와 같지 않을 때만 검사.
        if(first != second && second != third && first != third && second != 0 && third != 0){
           for(int i = 0; i < N; i++){
               strike_count = 0;
               ball_count = 0;
               //입력된 숫자와 검사한는 숫자의 자리와, 숫자가 같으면 strike_count++
               if(first == array[i].first){
                   strike_count++;
               }
               if(second == array[i].second){
                   strike_count++;
               }
               if(third == array[i].third){
                   strike_count++;
               }
               //겹치는 숫자가 있으면 ball_count++
               if(first == array[i].second || first == array[i].third){
                   ball_count++;
               }
               if(second == array[i].first || second == array[i].third){
                   ball_count++;
               }
               if(third == array[i].first || third == array[i].second){
                   ball_count++;
               }
               //검사하는 숫자의 ball과 strike가 모두 같으면 N_count++
               if(strike_count == array[i].strike && ball_count == array[i].ball){
                   N_count++;
               }
           }
           //입력된 모든경우에 대해 답이 될 수 있을 때
           if(N_count == N){
               answer++;
           }
        }

    } //123~987 for문 끝
    cout<<answer<<endl;;
    } //main

 

728x90