코드트리 - 메이즈러너 (Python)

Kim Yongbin·2024년 10월 15일
0

코딩테스트

목록 보기
157/162
import sys

# Solution
class Player:
    def __init__(self, id, x, y):
        self.id = id
        self.x = x
        self.y = y

    def move(self, nx, ny):
        self.x = nx
        self.y = ny

    def __repr__(self):
        return f"p{self.id}"

# Step 1: player 이동
def move_players():
    global move_dist
    escape_player_id_list = []

    for player in player_list:
        x, y = player.x, player.y
        dist = get_dist(x, y)

        for dx, dy in dirs:
            nx, ny = x + dx, y + dy
            n_dist = get_dist(nx, ny)

            if in_range(nx, ny) and maps[nx][ny] == 0 and dist > n_dist:
                move_dist += 1
                if n_dist == 0:
                    escape_player_id_list.append(player)
                    break
                player.move(nx, ny)
                break

    # 탈출
    for pid in escape_player_id_list:
        player_list.remove(pid)

# step 2: 가장 작은 정사각형 찾기
def find_square():
    curr = [N, N, N]

    for player in player_list:
        res = get_square(player)
        if curr > res:
            curr = res

    return curr

def get_square(player):
    point = [min(player.x, door[0]), min(player.y, door[1])]
    d = max(abs(player.x - door[0]), abs(player.y - door[1]))

    if max(player.x, door[0]) - point[0] < d:
        point[0] = max(max(player.x, door[0]) - d, 0)

    if max(player.y, door[1]) - point[1] < d:
        point[1] = max(max(player.y, door[1]) - d, 0)

    return [d + 1, *point]

def rotate(square_info):
    d, x, y = square_info
    new_graph = [[0] * d for _ in range(d)]

    for i in range(d):
        for j in range(d):
            if maps[x + i][y + j] > 0:
                new_graph[j][d - i - 1] = maps[x + i][y + j] - 1

    for i in range(d):
        for j in range(d):
            maps[x + i][y + j] = new_graph[i][j]

    for player in player_list:
        player.x, player.y = rotate_player_door(x, y, d, player.x, player.y)

    door[0], door[1] = rotate_player_door(x, y, d, door[0], door[1])

def rotate_player_door(x, y, d, target_x, target_y):
    after_x = target_x
    after_y = target_y

    if x <= target_x < x + d and y <= target_y < y + d:
        after_x = target_y - y + x
        after_y = d - target_x + x + y - 1

    return after_x, after_y

def get_dist(x, y):
    return abs(x - door[0]) + abs(y - door[1])

def in_range(x, y):
    return 0 <= x < N and 0 <= y < N

# main
N, M, K = map(int, sys.stdin.readline().split())
maps = []  # 0: 빈칸, 1 ~ 9: 벽
player_list = []  # 남아있는 player id list
door = []  # 탈출구
dirs = [[1, 0], [-1, 0], [0, 1], [0, -1]]
move_dist = 0

# set maps
for _ in range(N):
    maps.append(list(map(int, sys.stdin.readline().split())))

# set player
for i in range(1, M + 1):
    x, y = map(int, sys.stdin.readline().split())
    player = Player(i, x - 1, y - 1)
    player_list.append(player)

# set door
door_x, door_y = map(int, sys.stdin.readline().split())
door = [door_x - 1, door_y - 1]

# game
for i in range(K):
    move_players()
    if len(player_list) == 0:
        break
    square_info = find_square()
    rotate(square_info)

door[0] += 1
door[1] += 1

print(move_dist)
print(*door)
profile
반박 시 여러분의 말이 맞습니다.

0개의 댓글