프로그래밍/알고리즘

[Python] 백준 19237번 - 어른상어

고등어찌짐 2022. 9. 25. 23:50

쉽게 구현했으나 엣지 케이스를 통과하지 못해서 오래 헤맸다.

종료조건을 맞추지 못해 틀렸다. 

 

틀린 부분

if len(shark_dir) == 1 and 1 in shark_dir:
     break
elif ans > 1000:
     ans = -1
     break

 

이렇게 코드를 짜면, 1000초를 초과했더라도 상어가 1만 남았다면 -1 을 출력하지 못하게 된다. 그래서 조건 체크 순서를 바꾸어 줘야 맞다. 


수정 코드


# 현재 위치에 냄새 뿌림
# (상어 넘버, 냄새 값)
def spread_smell(b_arr, s_arr):
    for i in range(n):
        for j in range(n):
            if b_arr[i][j] > 0:
                s_arr[i][j] = (b_arr[i][j], k)
    return s_arr


# 다음 이동 좌표 결정
def get_coords():
    # 상 하 좌 우
    coord = {i: () for i in range(1, m+1)}
    gox = [0, -1, 1, 0, 0]
    goy = [0, 0, 0, -1, 1]

    for i in range(n):
        for j in range(n):
            chk = True
            shark_num = board[i][j]

            if shark_num > 0:
                curr_dir = shark_dir.get(shark_num)
                curr_order = dir_order.get(shark_num).get(curr_dir)

                # 좌표 범위 안이고, 아무 냄새가 없다면 이동
                for l in curr_order:
                    nx = gox[l] + i
                    ny = goy[l] + j
                    shark_dir[shark_num] = l
                    if 0 <= nx < n and 0 <= ny < n:
                        if smell[nx][ny][0] == 0:
                            coord[shark_num] = (nx, ny)
                            chk = False
                            break

                # 냄새가 없는 칸이 없으면 자신의 냄새가 있는 방향으로 이동
                if chk:
                    for l in curr_order:
                        nx = gox[l] + i
                        ny = goy[l] + j
                        shark_dir[shark_num] = l
                        if 0 <= nx < n and 0 <= ny < n:
                            if smell[nx][ny][0] == shark_num:
                                coord[shark_num] = (nx, ny)
                                break

    return coord


# 정해진 다음 좌표값으로 상어 움직임
def move(arr, dir_dict):
    arr = [[0 for _ in range(n)] for _ in range(n)]

    for s_num, cords in go_coord.items():
        # 여러 마리 있다면 상어 제거
        if cords:
            curr_s = arr[cords[0]][cords[1]]
            if curr_s > 0:
                if s_num < curr_s:
                    arr[cords[0]][cords[1]] = s_num
                    dir_dict.pop(curr_s)
                else:
                    dir_dict.pop(s_num)
            else:
                arr[cords[0]][cords[1]] = s_num

    return arr, dir_dict


# 냄새가 줄어듦
def dec_smell(arr):
    for i in range(n):
        for j in range(n):
            # 현재 칸에 상어가 있다
            if arr[i][j][0] > 0:
                # 냄새도 아직 남아 있다
                if arr[i][j][1] > 1:
                    arr[i][j] = (arr[i][j][0], arr[i][j][1]-1)
                else:
                    arr[i][j] = (0, 0)
    return arr


if __name__ == '__main__':
    n, m, k = map(int, input().split())
    board = [list(map(int, input().split())) for _ in range(n)]

    # 상어 현황과 각자의 방향을 저장
    shark_dir = {i+1: v for i, v in enumerate(map(int, input().split()))}

    # 각 상어들의 방향 우선순위
    dir_order = {i: {} for i in range(1, m+1)}
    for i in range(1, m+1):
        for j in range(1, 5):
            dir_order[i].update({j: list(map(int, input().split()))})

    ans = 0
    smell = [[(0, 0) for _ in range(n)] for _ in range(n)]

    while 1:
        # 1 번 상어만 격자에 남는 순간
        if ans > 1000:
            ans = -1
        elif len(shark_dir) == 1 and 1 in shark_dir:
            break

        # 현재 위치에 냄새를 뿌린다
        smell = spread_smell(board, smell)

        # 각 상어들이 이동할 방향을 결정한다  ( 다음 좌표 결정 )
        go_coord = get_coords()

        # 상어들이 움직이고
        board, shark_dir = move(board, shark_dir)

        # 냄새 수치 1 감소 ( 냄새는 상어 : k )
        smell = dec_smell(smell)

        ans += 1

    print(ans)