알고리즘/백준

0303. [BOJ#2578] 빙고

Jinoo.keem 2024. 3. 3. 21:14
728x90

https://www.acmicpc.net/problem/2578

 

2578번: 빙고

첫째 줄부터 다섯째 줄까지 빙고판에 쓰여진 수가 가장 위 가로줄부터 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 여섯째 줄부터 열째 줄까지 사회자가 부르는 수가 차례대로

www.acmicpc.net

1 초 128 MB 19945 9020 7394 45.684%

문제

빙고 게임은 다음과 같은 방식으로 이루어진다.

먼저 아래와 같이 25개의 칸으로 이루어진 빙고판에 1부터 25까지 자연수를 한 칸에 하나씩 쓴다

 

다음은 사회자가 부르는 수를 차례로 지워나간다. 예를 들어 5, 10, 7이 불렸다면 이 세 수를 지운 뒤 빙고판의 모습은 다음과 같다.

 

차례로 수를 지워가다가 같은 가로줄, 세로줄 또는 대각선 위에 있는 5개의 모든 수가 지워지는 경우 그 줄에 선을 긋는다.

 

이러한 선이 세 개 이상 그어지는 순간 "빙고"라고 외치는데, 가장 먼저 외치는 사람이 게임의 승자가 된다.

 

철수는 친구들과 빙고 게임을 하고 있다. 철수가 빙고판에 쓴 수들과 사회자가 부르는 수의 순서가 주어질 때, 사회자가 몇 번째 수를 부른 후 철수가 "빙고"를 외치게 되는지를 출력하는 프로그램을 작성하시오.

입력

첫째 줄부터 다섯째 줄까지 빙고판에 쓰여진 수가 가장 위 가로줄부터 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 여섯째 줄부터 열째 줄까지 사회자가 부르는 수가 차례대로 한 줄에 다섯 개씩 빈 칸을 사이에 두고 주어진다. 빙고판에 쓰여진 수와 사회자가 부르는 수는 각각 1부터 25까지의 수가 한 번씩 사용된다.

출력

첫째 줄에 사회자가 몇 번째 수를 부른 후 철수가 "빙고"를 외치게 되는지 출력한다.


제출 코드1

구현하다가 막혀서 강의보고 푼 코드

# 빙고판
arr = [list(map(int, input().split())) for _ in range(5)]   
# 빙고 체크 
check = []
for _ in range(5):
    check += map(int, input().split())

bing = [0] * 26
for i in range(5):
    for j in range(5):
        bing[arr[i][j]] = (i, j)
        
v = [[0] * 10 for _ in range(4)]

for num in check:
    i, j = bing[num]
    v[0][j] += 1 # 세로
    v[1][i] += 1 # 가로
    v[2][i-j] += 1 # 오른쪽아래
    v[3][i+j] += 1 # 오른쪽 위
    cnt = 0
    for result in v:
        cnt += result.count(5)
    if cnt >= 3:
        break
print(sum(v[0]))

빙고판의 가로 세로 대각, 역대각에 각각 v배열로 카운트 해주는 방식으로 풀어주셨는데.. 내가 보기엔 직관적이지 않아서 이해하는데 많은 어려움을 겪었다.

제출 코드2 

깨달음을 얻고 직접 구현

# 빙고검사
def bingo():
    global bingo_cnt
    
    # 가로빙고 확인
    for i in range(5):
        r_cnt = 0 # 한줄에 몇개 체크?
        for j in range(5):
            if visited[i][j]: # True
                r_cnt += 1
                if r_cnt == 5:
                    bingo_cnt += 1
    # 세로빙고 확인
    for i in range(5):
        c_cnt = 0 # 한줄에 몇개 체크?
        for j in range(5):
            if visited[j][i]: # True
                c_cnt += 1
                if c_cnt == 5:
                    bingo_cnt += 1
    # 정방향 대각빙고 확인
    cro_cnt = 0
    for i in range(5):
        if visited[i][i]: # True
            cro_cnt += 1
            if cro_cnt == 5:
                bingo_cnt += 1
    # 역방향 대각빙고 확인
    xcro_cnt = 0
    for i in range(5):
        if visited[4-i][i]: # True
            xcro_cnt += 1
            if xcro_cnt == 5:
                bingo_cnt += 1


# 빙고판
arr = [list(map(int, input().split())) for _ in range(5)]   
# 사회자가 부르는 순서 
check = []
for _ in range(5):
    check += map(int, input().split())
# 빙고체크
visited = [[False] * 5 for _ in range(5)]

bingo_cnt = 0
for k in check: # 숫자
        
    for i in range(5):
        for j in range(5):
            if arr[i][j] == k: # 빙고배열의 수와 사회자가 부른 수가 같을 때
                visited[i][j] = True # 체크
                bingo()
                if bingo_cnt >= 3:
                    result = k
                    break 
                else:
                    bingo_cnt = 0 # 초기화
                    continue
        if bingo_cnt >= 3:
            break 
    if bingo_cnt >= 3:
        break 

ans = 0
for x in check:
    ans += 1
    if result == x:
        print(ans)
        break

사회자가 부르는 값을 넣는 구현이 생각보다 까다로웠고,

그 후에는 사회자가 부르는 숫자를 순서대로 부르면서 빙고판의 숫자와 대조시켜주었다.

값이 같을 때 visited를 이용해 체크를 한 후 bingo함수로 들어가서 3개이상의 빙고인지 확인해주었고,

아니라면 다시 빙고카운트값을 0으로 초기화하는 식으로 진행했다.

만약,

빙고카운트가 3이상이라면 포문을 빠져나와서 빙고카운트가 3이 될 때,

사회자가 부른 값이 몇번째인지 세어주면서 마무리 했다.

생각보다 많이 어렵다고 느껴서 내일있을 시험이 두려워지는 하루당

'알고리즘 > 백준' 카테고리의 다른 글

0306. [BOJ#4779] 칸토어 집합  (2) 2024.03.06
0305. [BOJ#1244] 스위치 켜고 끄기  (0) 2024.03.05
0302. [BOJ#2628] 종이 자르기  (0) 2024.03.02
0301. [BOJ#2468] 안전영역  (0) 2024.03.01
0228. [BOJ#2846] 오르막길  (1) 2024.02.28