⏰문제
https://www.acmicpc.net/problem/2578
빙고 게임은 다음과 같은 방식으로 이루어진다.
먼저 아래와 같이 25개의 칸으로 이루어진 빙고판에 1부터 25까지 자연수를 한 칸에 하나씩 쓴다
다음은 사회자가 부르는 수를 차례로 지워나간다. 예를 들어 5, 10, 7이 불렸다면 이 세 수를 지운 뒤 빙고판의 모습은 다음과 같다.
차례로 수를 지워가다가 같은 가로줄, 세로줄 또는 대각선 위에 있는 5개의 모든 수가 지워지는 경우 그 줄에 선을 긋는다.
이러한 선이 세 개 이상 그어지는 순간 "빙고"라고 외치는데, 가장 먼저 외치는 사람이 게임의 승자가 된다.
철수는 친구들과 빙고 게임을 하고 있다. 철수가 빙고판에 쓴 수들과 사회자가 부르는 수의 순서가 주어질 때, 사회자가 몇 번째 수를 부른 후 철수가 "빙고"를 외치게 되는지를 출력하는 프로그램을 작성하시오.
입력
첫째 줄부터 다섯째 줄까지 빙고판에 쓰여진 수가 가장 위 가로줄부터 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 여섯째 줄부터 열째 줄까지 사회자가 부르는 수가 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 빙고판에 쓰여진 수와 사회자가 부르는 수는 각각 1부터 25까지의 수가 한 번씩 사용된다.
출력
첫째 줄에 사회자가 몇 번째 수를 부른 후 철수가 "빙고"를 외치게 되는지 출력한다.
예제 입력 1
11 12 2 24 10
16 1 13 3 25
6 20 5 21 17
19 4 8 14 9
22 15 7 23 18
5 10 7 16 2
4 22 8 17 13
3 18 1 6 25
12 19 23 14 21
11 24 9 20 15
예제 출력 1
15
💡풀이
1. 사회자가 숫자를 불러줄때마다 빙고인지 판단하기 -> Check함수
2. 빙고가 3개가 달성하면 그 즉시 for문을 벗어나고 몇 번째에 for문을 빠져나왔는지 결과값을 출력한다.
빙고는 행, 열, 대각선 2개(좌상-> 우하, 우상 -> 좌하), 총 4개를 판단해야한다.
행과 열은 int배열을 만들어서 판단을 해줬다.
예제1을 이용해 본다면 사회자가 부른 숫자를 빙고판에서 어디에 위치했는지 (r,c)점을 찾아서 R배열과 C배열의 index와 매칭시켜주었다.
5 -> (2,2) -> r[2]++; c[2]++;
그리고 대각선은 좌상-> 우하일 때는 r==c라는 점을 이용했고, 우상 -> 좌하는 r+c =4라는 규칙을 이용했다.
각각 5개라는 숫자에 도달했다는 것은 해당 행이나 열, 대각선이 빙고를 했다는 뜻이므로 체크를 해주었다.
⌨️ 코드
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.StringTokenizer;
public class Main {
static final int N = 5;
static int[] r = new int[N]; //행 빙고인지 판단
static int[] c = new int[N]; //열 빙고인지 판단
static int[][] bingo; //빙고판
static int left,right; //왼쪽시작 대각선, 오른쪽시작대각선
static int letBingo; //빙고의 개수
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
bingo = new int[N][N];
StringTokenizer st;
for(int i = 0; i< N; i++){
st = new StringTokenizer(br.readLine());
for(int j=0; j<N; j++){
bingo[i][j] = Integer.parseInt(st.nextToken());
}
}
int cnt =0;
int answer = 0;
left = 0;
right = 0;
letBingo = 0;
outer : for(int i=0; i <N; i++){
st = new StringTokenizer(br.readLine());
for(int j=0; j<N; j++){
int num = Integer.parseInt(st.nextToken()); //사회자가 불러주는 숫자
cnt++; //몇 번째 숫자인지
//빙고인지 확인
if(Check(num)){
answer = cnt;
break outer;
}
}
}
System.out.println(answer);
}
private static boolean Check(int num) { //사회자가 부른 숫자
for(int i=0; i< N; i++){ //빙고를 돌아
for(int j=0; j< N; j++){
if(num == bingo[i][j]){
r[i]++;
c[j]++;
//둘 다 if를 하지 않으면 빙고맵에서 (2,2)가 나올 때 체크를 못 해줌
if(i == j) left++;
if(i+j == 4) right++;
}
}
}
if(left == 5) {
letBingo++;
left =0;
}
if(right == 5){
letBingo++;
right = 0;
}
for(int i=0; i< N; i++){
if(r[i] == 5) {
letBingo++;
r[i] = 0;
}
if(c[i] == 5) {
letBingo++;
c[i] = 0;
}
}
if(letBingo >= 3){
return true;
}
return false;
}
}
📣 comment
문제를 풀면서 동시성에 대해서 생각을 못 했었다. 예를 들자면 한 숫자가 사회자에게 불림으로서 여러개가 동시다발적으로 빙고가 될 수 있다는 것이다. 이것을 놓쳐서 코드를 수정하기도 했다.
if-else 구문이 아닌 if-if로 처리를 해주었고, 초기에는 letBingo라는 변수가 3일때만 쓰리빙고로 true값을 리턴했는데, 동시에 빙고가 나와서 3 이상으로 나올 수 있어서 letBingo를 3이상으로 조건을 걸었다.
사용하는 변수도 많아지고 조건도 촘촘하게 짜야해서 어려웠지만 실력이 늘은 것 같은 기분이 든다^^
'⚙️알고리즘' 카테고리의 다른 글
백준 23796) 2,147,483,648 게임 (0) | 2024.07.11 |
---|---|
백준 2206 ) 벽 부수고 이동하기 (2) | 2024.07.07 |
백준) 1316 : 그룹 단어 체커 (0) | 2024.02.16 |
백준) 2630 : 색종이 만들기 (0) | 2024.02.14 |
백준) 1654 : 랜선 자르기 (0) | 2024.02.06 |