PS/백준

23290번 - 마법사 상어와 복제

ForteQook 2022. 10. 1. 16:29

문제

23290번: 마법사 상어와 복제 (acmicpc.net)

 

23290번: 마법사 상어와 복제

첫째 줄에 물고기의 수 M, 상어가 마법을 연습한 횟수 S가 주어진다. 둘째 줄부터 M개의 줄에는 물고기의 정보 fx, fy, d가 주어진다. (fx, fy)는 물고기의 위치를 의미하고, d는 방향을 의미한다. 방향

www.acmicpc.net

풀이

물고기의 이동 제한 조건은 상어의 존재, 보드 경계 그리고 냄새이다.

냄새는 생성되는 턴에 한번, 그리고 그로부터 두턴 더 남아있기 때문에 총 세번의 반복문을 돌고나면 0이된다는 점에 주의하자.

상어는 최적의 이동경로를 먼저 탐색한 뒤 그 경로를 따라 이동한다. 경로 탐색은 이동경로에 있는 물고기 숫자의 합과 이동경로 자체에 의해 결정되는데, 이는 heapq를 이용하면 간단하게 구현가능하다. 주의할 점은 상어의 이동경로가 중복될 수 있다는 것인데, 따라서 방문여부로 백트래킹을 하면 안되고 3번 이동하면서 재방문한 칸에있는 물고기숫자는 재귀함수에 더해주지 않는 방식으로 구현해야한다.

import heapq

# W,NW,N,NE,E,SE,S,SW
dRow = [0,0,-1,-1,-1,0,1,1,1]
dCol = [0,-1,-1,0,1,1,1,0,-1]
# 상좌하우
dsx = [0,-1,0,1,0]
dsy = [0,0,-1,0,1]
P = ['','1','2','3','4']

M,S = map(int,input().split())
board = [[[] for row in range(5)] for col in range(5)]
for _ in range(M):
    fx,fy,d = map(int,input().split())
    board[fx][fy].append(d)
sx,sy = map(int,input().split())
smells = [[0]*5 for _ in range(5)]


def get_route(cnt,x,y,num,pth):
    if cnt >= 3:
        heapq.heappush(heap,((-num,int(pth)),pth))
        return
    for i in range(1,5):
        nx,ny = x+dsx[i],y+dsy[i]
        if 1 <= nx <= 4 and 1 <= ny <= 4:
            dnum = len_board[nx][ny]
            len_board[nx][ny] = 0
            get_route(cnt+1,nx,ny,num+dnum,pth+P[i])
            len_board[nx][ny] = dnum


for _ in range(S):
    # 복제 마법
    cpy = [[[*b] for b in a] for a in board]
    # 물고기 이동
    new_board = [[[] for row in range(5)] for col in range(5)]
    for row in range(1,5):
        for col in range(1,5):
            if board[row][col]:
                for i in range(len(board[row][col])):
                    d = board[row][col].pop()
                    for j in range(1,9):
                        nd = (8+d-j)%8+1
                        nRow,nCol = row+dRow[nd],col+dCol[nd]
                        if 1 <= nRow <= 4 and 1 <= nCol <= 4 and smells[nRow][nCol] == 0 and not (nRow == sx and nCol == sy):
                            new_board[nRow][nCol].append(nd)
                            break
                    else:
                        new_board[row][col].append(d)
    # 상어 이동경로 찾기
    len_board = [[len(b) for b in a] for a in new_board]
    heap = []
    get_route(0,sx,sy,0,'')
    # 상어 이동
    for i in map(int,heap[0][1]):
        sx += dsx[i]
        sy += dsy[i]
        if new_board[sx][sy]:
            new_board[sx][sy].clear()
            smells[sx][sy] = 3
    # 냄새 갱신, 마법 완료
    for row in range(1, 5):
        for col in range(1, 5):
            if smells[row][col] > 0:
                smells[row][col] -= 1
            board[row][col] = [*new_board[row][col]] + [*cpy[row][col]]


answer = 0
for row in range(1,5):
    for col in range(1,5):
        if board[row][col]:
            answer += len(board[row][col])
print(answer)

 

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

15686번 - 치킨 배달  (0) 2022.10.10
23291번 - 어항 정리  (0) 2022.10.01
21611번 - 마법사 상어와 블리자드  (1) 2022.10.01
21610번 - 마법사 상어와 비바라기  (1) 2022.09.30
23289번 - 온풍기 안녕!  (1) 2022.09.30