[Samsung] 2022-2 오후 1번 코드트리빵

Question

Language: Python

Difficulty: Gold 2

해당 문제는 주어진 시뮬레이션 과정을 구현하면 되는 문제이다.

  1. 베이스캠프에서 편의점 방향으로 이동
  2. 편의점에 도달한 사람의 경우 해당 자리를 더 이상 접근하지 못하도록 방지
  3. 베이스캠프에 사람이 도착
  1. 베이스캠프 -> 편의점 이동

베이스캠프에서 편의점까지의 경로 중에서 최소 경로에 위치한 좌표를 찾기 위해 역으로 bfs을 실행한다. 편의점을 기준으로 bfs을 실행하여 각각의 좌표점에 대한 거리를 초기화 해서, 현재 위치 좌표의 상,우,좌,하 방향의 거리값을 비교해서 최소 거리값에 위치한 좌표로 이동한다.

queue=deque([(0,store_location[0],store_location[1])])
distances=[[inf]*n for _ in range(n)]

while queue:
    distance,row,col=queue.popleft()

    if distance > distances[row][col]:
        continue
    distances[row][col]=distance

    if (row,col)==current_location:
        continue
    
    for dir in range(4):
        next_row=row+dy[dir]
        next_col=col+dx[dir]

        #격자를 벗어난 경우
        if next_row < 0 or next_row >=n or next_col < 0 or next_col>=n:
            continue
        
        #지나갈 수 없는자리
        if board[next_row][next_col] == -1:
            continue
        #거리가 짧은 경우에만 도달
        if distance + 1 < distances[next_row][next_col]:
            distances[next_row][next_col]=distance+1
            queue.append((distance+1,next_row,next_col))

candidates=[]
#해당 위치에서 다음 위치의 후보 찾기
for dir in range(4):
    next_row=current_location[0]+dy[dir]
    next_col=current_location[1]+dx[dir]

    #격자를 벗어난 경우
    if next_row < 0 or next_row >=n or next_col < 0 or next_col>=n:
        continue
    candidates.append((distances[next_row][next_col],dir,next_row,next_col))

candidates.sort(key=lambda x: (x[0],x[1]))
return candidates[0][2],candidates[0][3]
  1. 편의점에 도달한 사람의 경우, 해당 자리를 더 이상 접근하지 못하도록 접근 방지 처리를 한다.
#편의점에 도달한 사람의 위치는 더 이상 다른 사람들이 방문하지 못하도록 한다.
number_of_person=0
while number_of_person < m and locations[number_of_person] != (-1,-1):
    #이전에 도착 처리를 하지 않은 사람 중에서 편의점에 도착한 경우 도착 처리를 진행한다.
    if not arrived[number_of_person] and locations[number_of_person]==stores[number_of_person]:
        board[stores[number_of_person][0]][stores[number_of_person][1]]=-1
        arrived[number_of_person]=True
        count_of_arrived+=1
    number_of_person+=1
  1. 편의점에서 가장 가까운 베이스캠프에 사람을 위치시킨다.

1번과 유사한 방식으로, 편의점을 기준으로 bfs을 동작시켜서 가장 가까운 베이스 캠프를 구한다.

queue=deque([(0,store_location[0],store_location[1])])
visited=[[False]*n for _ in range(n)]
parking_lots=[]
while queue:
    distance,row,col=queue.popleft()
    
    if visited[row][col]:
        continue
    visited[row][col]=True

    if board[row][col]==1:
        parking_lots.append((distance,row,col))

    for dir in range(4):
        next_row=row+dy[dir]
        next_col=col+dx[dir]
        
        #격자를 벗어난 경우
        if next_row < 0 or next_row >=n or next_col < 0 or next_col>=n:
            continue

        #해당 자리가 이미 차지한 자리인 경우(베이스캠프, 편의점)
        if board[next_row][next_col] == -1:
            continue

        queue.append((distance+1,next_row,next_col))
        
#거리순, 행순, 열순으로 정렬해서 가장 첫번째 값을 반환
parking_lots.sort()

return parking_lots[0][1],parking_lots[0][2] 

Solution

from collections import deque
from math import inf

#주차장을 찾기 위한 bfs
def find_parking_lot(store_location):
    queue=deque([(0,store_location[0],store_location[1])])
    visited=[[False]*n for _ in range(n)]
    parking_lots=[]
    while queue:
        distance,row,col=queue.popleft()
        
        if visited[row][col]:
            continue
        visited[row][col]=True

        if board[row][col]==1:
            parking_lots.append((distance,row,col))

        for dir in range(4):
            next_row=row+dy[dir]
            next_col=col+dx[dir]
            
            #격자를 벗어난 경우
            if next_row < 0 or next_row >=n or next_col < 0 or next_col>=n:
                continue

            #해당 자리가 이미 차지한 자리인 경우(베이스캠프, 편의점)
            if board[next_row][next_col] == -1:
                continue

            queue.append((distance+1,next_row,next_col))
            
    #거리순, 행순, 열순으로 정렬해서 가장 첫번째 값을 반환
    parking_lots.sort()

    return parking_lots[0][1],parking_lots[0][2]        

#편의점 방향으로 이동하기 위한 함수
def move_to_store(store_location,current_location):
    queue=deque([(0,store_location[0],store_location[1])])

    distances=[[inf]*n for _ in range(n)]

    while queue:
        distance,row,col=queue.popleft()

        if distance > distances[row][col]:
            continue
        distances[row][col]=distance

        if (row,col)==current_location:
            continue
        
        for dir in range(4):
            next_row=row+dy[dir]
            next_col=col+dx[dir]

            #격자를 벗어난 경우
            if next_row < 0 or next_row >=n or next_col < 0 or next_col>=n:
                continue
            
            #지나갈 수 없는자리
            if board[next_row][next_col] == -1:
                continue
            #거리가 짧은 경우에만 도달
            if distance + 1 < distances[next_row][next_col]:
                distances[next_row][next_col]=distance+1
                queue.append((distance+1,next_row,next_col))
    
    candidates=[]
    #해당 위치에서 다음 위치의 후보 찾기
    for dir in range(4):
        next_row=current_location[0]+dy[dir]
        next_col=current_location[1]+dx[dir]

        #격자를 벗어난 경우
        if next_row < 0 or next_row >=n or next_col < 0 or next_col>=n:
            continue
        candidates.append((distances[next_row][next_col],dir,next_row,next_col))

    candidates.sort(key=lambda x: (x[0],x[1]))
    return candidates[0][2],candidates[0][3]

def print_board():
    for row in board:
        print(*row)


def solution():
    global board
    time=0
    #각 사용자들의 베이스캠프 저장
    camps=[(-1,-1)] * m

    #각 사용자들의 위치 좌표 저장
    locations=[(-1,-1)] *m

    #도착한 사람들의 정보
    arrived=[False]*m
    count_of_arrived=0

    #모든 사용자들이 편의점에 도달할 때까지 반복 진행
    while count_of_arrived <m:

        #편의점 방향으로 이동
        number_of_person=0
        while number_of_person < m and locations[number_of_person] != (-1,-1):
            #아직 편의점에 도달하지 않은 경우에만 이동한다.
            if not arrived[number_of_person]:
                new_location=move_to_store(stores[number_of_person],locations[number_of_person])
                locations[number_of_person]=new_location

            number_of_person+=1
        
        #편의점에 도달한 사람의 위치는 더 이상 다른 사람들이 방문하지 못하도록 한다.
        number_of_person=0
        while number_of_person < m and locations[number_of_person] != (-1,-1):
            #이전에 도착 처리를 하지 않은 사람 중에서 편의점에 도착한 경우 도착 처리를 진행한다.
            if not arrived[number_of_person] and locations[number_of_person]==stores[number_of_person]:
                board[stores[number_of_person][0]][stores[number_of_person][1]]=-1
                arrived[number_of_person]=True
                count_of_arrived+=1
            number_of_person+=1

        #베이스 캠프 찾아서, 사용자를 위치 시키고, 해당 자리는 영구적으로 방문 제외 처리
        if time < m:
            parking_lot=find_parking_lot(stores[time])
            locations[time]=parking_lot
            camps[time]=parking_lot
            board[parking_lot[0]][parking_lot[1]]=-1
        time+=1
    print(time)

if __name__ == "__main__":
    n,m=map(int,input().split())
    board=[list(map(int,input().split())) for _ in range(n)]
    stores=[tuple(map(lambda x: int(x)-1,input().split())) for _ in range(m)]
    
    dy=[-1,0,0,1]
    dx=[0,-1,1,0]

    solution()

댓글남기기