코드트리 - 루돌프 반란 (Python)

Kim Yongbin·2024년 10월 15일
0

코딩테스트

목록 보기
159/162
import sys

# Solution
class Santa:
    def __init__(self, id, x, y):
        self.id = id
        self.x = x
        self.y = y
        self.status = 0

    def __lt__(self, other):
        return (get_distance(self.x, self.y), -self.x, -self.y) < (get_distance(other.x, other.y), -other.x, -other.y)

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

# step 1: 루돌프 이동
def move_rudolph():
    maps[rudolph[0]][rudolph[1]] = 0

    target = get_santa()
    dir = get_rudolph_dir(target)

    nx, ny = rudolph[0] + dir[0], rudolph[1] + dir[1]

    # 충돌
    if maps[nx][ny] > 0:
        santa_id = maps[nx][ny]
        santa = santa_dict[santa_id]

        santa.status = -2  # santa 기절
        santa_score[santa_id] += C  # santa C점 획득

        interaction(santa, dir, C)

    rudolph[0] = nx
    rudolph[1] = ny
    maps[nx][ny] = -1

def get_santa():
    sorted_list = sorted(santa_dict.values())
    return sorted_list[0]

def get_rudolph_dir(santa):
    len_x = santa.x - rudolph[0]
    len_y = santa.y - rudolph[1]

    dx = 0 if len_x == 0 else len_x // abs(len_x)
    dy = 0 if len_y == 0 else len_y // abs(len_y)

    return [dx, dy]

# step 2: 산타 이동
def move_santa():
    for santa_id in range(1, P + 1):
        # 아웃 당한 산타
        if santa_id not in santa_dict.keys():
            continue

        santa = santa_dict[santa_id]
        # 기절한 산타
        if santa.status < 0:
            continue
        dir = get_santa_dirs(santa)
        # 이동 불가
        if dir is None:
            continue

        nx, ny = santa.x + dir[0], santa.y + dir[1]
        maps[santa.x][santa.y] = 0
        santa.x = nx
        santa.y = ny

        if maps[nx][ny] == -1:
            santa_score[santa_id] += D
            santa.status = -2
            dir[0] *= -1
            dir[1] *= -1
            interaction(santa, dir, D)
        else:
            maps[nx][ny] = santa_id

def get_santa_dirs(santa):
    dist = get_distance(santa.x, santa.y)
    next = None

    for dir in dirs:
        nx, ny = santa.x + dir[0], santa.y + dir[1]
        curr = get_distance(nx, ny)
        if in_range(nx, ny) and maps[nx][ny] <= 0 and dist > curr:
            dist = curr
            next = [dir[0], dir[1]]

    return next

# step 3: 상호작용
def interaction(santa, dir, length):
    nx = santa.x + dir[0] * length
    ny = santa.y + dir[1] * length

    if not in_range(nx, ny):
        del santa_dict[santa.id]
        return

    if maps[nx][ny] > 0:
        new_santa = santa_dict[maps[nx][ny]]
        interaction(new_santa, dir, 1)

    santa.x = nx
    santa.y = ny
    maps[santa.x][santa.y] = santa.id

# Step 4: 살아남은 산타 점수 획득
def get_score():
    for santa_id in santa_dict.keys():
        santa_score[santa_id] += 1
        santa = santa_dict[santa_id]
        if santa.status < 0:
            santa.status += 1

# 기타
def get_distance(x, y):
    return pow(x - rudolph[0], 2) + pow(y - rudolph[1], 2)

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

# main
# N: map 크기, M: 게임 턴 수, P: 산타 수, C: r->s 점수, D: s->r 점수
N, M, P, C, D = map(int, sys.stdin.readline().split())
maps = [[0] * N for _ in range(N)]
santa_dict = {}
santa_score = [0] * (P + 1)
rudolph = []
dirs = [(-1, 0), (0, 1), (1, 0), (0, -1)]

# get rudolph
r, c = map(int, sys.stdin.readline().split())
rudolph = [r - 1, c - 1]
maps[r - 1][c - 1] = -1

# get santa
for _ in range(P):
    id, r, c = map(int, sys.stdin.readline().split())
    santa = Santa(id, r - 1, c - 1)
    santa_dict[id] = santa
    maps[santa.x][santa.y] = santa.id

# game
for _ in range(M):
    move_rudolph()
    move_santa()
    if len(santa_dict) == 0:
        break
    get_score()

print(*santa_score[1:])
profile
반박 시 여러분의 말이 맞습니다.

0개의 댓글