📕문제
정보문화진흥원 정보 영재 동아리에서 동아리 활동을 하던 영수와 민혁이는 쉬는 시간을 틈타 숫자야구 게임을 하기로 했다.
- 영수는 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, 이렇게 두 가지이다.
영수는 동아리의 규율을 잘 따르는 착한 아이라 민혁이의 물음에 곧이곧대로 정직하게 답한다. 그러므로 영수의 답들에는 모순이 없다.
민혁이의 물음들과 각각의 물음에 대한 영수의 답이 입력으로 주어질 때 영수가 생각하고 있을 가능성이 있는 답의 총개수를 출력하는 프로그램을 작성하시오.
📕입력
첫째 줄에는 민혁이가 영수에게 몇 번이나 질문을 했는지를 나타내는 1 이상 100 이하의 자연수 N이 주어진다. 이어지는 N개의 줄에는 각 줄마다 민혁이가 질문한 세 자리 수와 영수가 답한 스트라이크 개수를 나타내는 정수와 볼의 개수를 나타내는 정수, 이렇게 총 세 개의 정수가 빈칸을 사이에 두고 주어진다.
📕출력
첫 줄에 영수가 생각하고 있을 가능성이 있는 답의 총 개수를 출력한다.
💡문제해석
- 민혁이와 영수는 서로 다른 3가지의 숫자를 통해서 세 자릿수를 구성한다.
- 범위는 1~9까지이다. [0을 신경 써야 한다. 안 쓰면 통과 못함 ㅠㅠ]
- 반복문을 돌린다.
- 서로 다른 3가지 숫자로 구성된 숫자 중 가장 작은 값인 123
- 서로 다른 3가지 숫자로 구성된 숫자중 가장 큰 값인 987
- 즉 123~987의 범위를 반복문으로 돌린다.
- 여기서 조건을 걸어줘야 한다.
- 세 자리 숫자는 서로 다른 숫자로 구성되어야 하고, 0을 포함하면 안 된다.
- 입력받은 숫자와 반복문을 통해서 돌아가는 숫자를 비교해서 우리가 입력받은 strike, ball을 얻어내야 한다.
- strike는 3자리끼리 비교해서 숫자도 같고, index도 같은 경우 strike를 ++해준다.
- ball은 3자리 끼리 비교해서 숫자가 같지만, index가 다른 경우 ball을 ++해준다.
- 이렇게 얻어낸 strike, ball과 입력받은 strike, ball이 같아야 숫자 후보의 포함된다.
- 이렇게 끝까지 돌려서 포함된 숫자의 개수가 영수가 생각할 수 있는 답의 개수가 될 것이다.
📕코드
/*2503 숫자야구
숫자는 1~9 , 서로 다른 3글자
내가 부른 숫자와 자리가 일치하다면 스트라이크
숫자는 일치한데 자리가 다르면 볼
*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
bool same(int num);
int baseball(int num, int cnum);
int c, s, b, n, Count = 0;
int main()
{
cin >> n;
vector<int> T(988, -1);
for (int i = 0; i < n; i++)
{
cin >> c >> s >> b;
for (int j = 123; j <= 987; j++)
{ //서로 다른 숫자여야함.
if (same(j)) // 1이 출력되면 같은 숫자니까 넘김.
continue;
else
{
if (baseball(c, j))
{ //내가 생각한 s,b가 일치하다면?
if (T[j] == -1) //한번이라도 걸러지면 안됨.
T[j] = 1;
}
else //다르다면?
T[j] = 0; //한번이라도 제외되면 컷. 해야함.
}
}
}
for (int i = 123; i <= 987; i++)
{
if (T[i] == 1)
Count++;
}
cout << Count;
// count 넣고 strike ball 넣엇음.
}
bool same(int num)
{
int A, B, C;
A = num / 100; //백의자리
num = num % 100;
B = num / 10; // 10의 자리?
C = num % 10;
if (A == 0 || B == 0 || C == 0)
return true;
else if (A - B == 0 || A - C == 0 || B - C == 0)
return true;
else
return false;
}
int baseball(int num, int cnum)
{
int strike = 0, ball = 0;
vector<int> old(3, 0), New(3, 0);
old[0] = num / 100; //백의자리
num = num % 100;
old[1] = num / 10; // 10의 자리?
old[2] = num % 10; // 1의 자리
New[0] = cnum / 100; //백의자리
cnum = cnum % 100;
New[1] = cnum / 10; // 10의 자리
New[2] = cnum % 10; // 1의 자리
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (old[i] == New[j])
{ //숫자가 같을 때
if (i == j)
{ // 자리수가 같다면?
strike++;
}
else
ball++;
}
}
}
if (s == strike && b == ball)
return 1;
else
return 0;
}
✔느낀 점
- 처음에는 체계적으로 짜려고 했는데 쉽지가 않아서 브루트 포스 알고리즘을 선택했다.
- 나는 반복문을 4번 돌리고 거기서 123~987까지 탐색했는데, n번을 싹 다 입력받고 각각의 경우에 대해서 비교하는 것이 훨씬 효율적이었을 것 같다.
'CodingTest > Baekjoon' 카테고리의 다른 글
[백준 9935]-문자열폭발(C++) (0) | 2022.07.19 |
---|---|
[백준 1577]-다리 개수 구하기(C++) (0) | 2022.07.08 |
[백준 11052]-카드 구매하기(C++) (0) | 2022.07.07 |
[백준 11053]-가장 긴 증가하는 부분 수열(C++) (0) | 2022.07.06 |
[백준 12865]-평범한 배낭(C++) (0) | 2022.07.06 |