Algorithm

백준 16768번 <Mooyo Mooyo>

seungh2 2022. 2. 8. 23:47

백준 알고리즘 16768번

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

 

16768번: Mooyo Mooyo

In the example above, if $K = 3$, then there is a connected region of size at least $K$ with color 1 and also one with color 2. Once these are simultaneously removed, the board temporarily looks like this: 0000000000 0000000300 0054000300 1054500030 220000

www.acmicpc.net


16768번

입력으로 첫 줄에 board의 행 수 N이 들어오고 연결된 블록의 수 K가 들어온다.

그 다음 N개의 줄에 걸쳐 board의 상태가 들어온다.

 

출력으로는 MooyoMooyo 게임을 모두 진행된 board의 상태를 출력한다.


문제 해결

뿌요뿌요와 비슷한 게임이다.

 

1. board에서 한 숫자가 K개 이상 인접해있으면 0으로 바꾼다.

2. board에서 0이 아닌 숫자 밑에 0이 있다면 그 0을 없애고 해당 숫자를 밑으로 내린다.

 

1번은 bfs함수와 zero함수를 이용하여 구현하였고

2번은 down 함수를 이용하여 구현하였다.

 

bfs(i, j, chk, N, K)

- bfs 알고리즘을 이용하여 (i, j) 좌표와 인접하고 chk의 값과 Map[i][j]의 값이 같은 좌표들을 coordinate에 저장하였다.

- set(coordinate)의 길이가 K보다 같거나 크다면 zero(coordinata) 함수를 호출한다.

- i, j 좌표는 처음에 coordinate에 저장되지 않지만 인접 좌표들의 인접 좌표로 되서 들어가게 된다.

 

zero(coordinate)

- coordinate에 저장되어 있는 좌표의 Map 값을 0으로 바꾸고 visit 값을 True로 바꾼다.

 

down()

- 0이 아닌 숫자 밑에 0이 없도록 해당 숫자를 밑으로 내린다.

- 이때 idx를 이용하여 0인 경우에는 0인 경우는 continue, idx와 for문의 i값과 같다면 idx에서 1을 빼고 i, j 좌표의 newMap의 값에 i, j 좌표의 Map의 값을 가져온다. 이 2가지 경우가 아닌 경우에는 idx, j 좌표의 newMap의 값에 i, j 좌표의 Map의 값을 가져오고 idx에서 1을 뺀다.

- 게임이 끝나는 경우를 알기 위해 check 변수를 이용하여 board 상태가 변하는 경우(False)와 변하지 않는 경우(True)를 구분한다.

 

visit 배열을 이용하여 Map에서 방문한 좌표를 저장해둔다.

Map이 게임이 진행되면서 바뀌기 때문에 visited 함수를 이용하여 Map에 대한 visit 배열을 update 한다.


코드

from collections import deque

N, K = map(int, input().split())
Map = [[0 for _ in range(10)] for _ in range(N)]
visit = [[False for _ in range(10)] for _ in range(N)]

for i in range(N):
    temp = input()
    for j in range(10):
        Map[i][j] = int(temp[j])
        if Map[i][j] == 0:
            visit[i][j] = True

def visited():
    for i in range(N):
        for j in range(10):
            if Map[i][j] == 0:
                visit[i][j] = True
            else:
                visit[i][j] = False

def zero(coordinate):
    for a, b in coordinate:
        Map[a][b] = 0
        visit[a][b] = True

def bfs(i, j, chk, N, K):
    di = [1, -1, 0, 0]
    dj = [0, 0, 1, -1]
    q = deque([(i, j)])
    coordinate = []
    while q:
        mi, mj = q.popleft()
        for k in range(4):
            newI = mi + di[k]
            newJ = mj + dj[k]
            if newI >= N or newJ >= 10 or newI < 0 or newJ < 0:
                continue
            if not visit[newI][newJ] and Map[newI][newJ] == chk:
                q.append((newI, newJ))
                coordinate.append((newI, newJ))
                visit[newI][newJ] = True
    if len(set(coordinate)) >= K:
        zero(coordinate)
def down(N):
    check = True
    newMap = [[0 for _ in range(10)] for _ in range(N)]
    for j in range(10):
        idx = N-1
        for i in range(N-1, -1, -1):
            if Map[i][j] == 0:
                continue
            if idx == i:
                idx -= 1
                newMap[i][j] = Map[i][j]
                continue
            check = False
            newMap[idx][j] = Map[i][j]
            idx -= 1
    if check:
        return Map, check  
    return newMap, check

        
while True:
    for i in range(N):
        for j in range(10):
            if visit[i][j]:
                continue
            chk = Map[i][j]
            bfs(i, j, chk, N, K)
    Map, check = down(N)
    if check:
        break
    visited()
            
for i in range(N):
    for j in range(10):
        print(Map[i][j], end="")
    print("")

결과


 

728x90