코드트리 - 왕실의 기사대결 (Python)

Kim Yongbin·2024년 10월 15일
0

코딩테스트

목록 보기
158/162
import sys

# Solution
class Knight:
    def __init__(self, id, x, y, h, w, k):
        self.id = id
        self.x = x
        self.y = y
        self.h = h
        self.w = w
        self.life = k
        self.damage = 0

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

def move_knight(op):
    k_id, d_idx = op

    # 없는 기사 예외처리
    if k_id not in knight_dict.keys():
        return
    knight = knight_dict[k_id]
    dir = dirs[d_idx]

    moved_set = push(knight, dir, set())
    if moved_set is not None:
        move(moved_set, k_id, dir)

def push(knight, dir, pushed_knight_set):
    x, y = knight.x, knight.y

    for i in range(knight.h):
        for j in range(knight.w):
            nx = x + i + dir[0]
            ny = y + j + dir[1]

            # 벽
            if not in_range(nx, ny) or maps[nx][ny] == 2:
                return None

            # 자기 자신
            if knight_map[nx][ny] == knight.id:
                continue

            # 다른 기사
            if knight_map[nx][ny] > 0 and knight_map[nx][ny] not in pushed_knight_set:
                next_knight_id = knight_map[nx][ny]
                next_knight = knight_dict[next_knight_id]
                res = push(next_knight, dir, pushed_knight_set)
                if res is None:
                    return None
                pushed_knight_set.update(res)

    pushed_knight_set.add(knight.id)
    return pushed_knight_set

def move(knight_id_set, attk_id, dir):
    # knight map reset
    for knight_id in knight_id_set:
        knight = knight_dict[knight_id]
        for i in range(knight.h):
            for j in range(knight.w):
                knight_map[knight.x + i][knight.y + j] = 0

        knight.x += dir[0]
        knight.y += dir[1]

    # knight map 재 세팅 및 체력 감소
    for knight_id in knight_id_set:
        knight = knight_dict[knight_id]
        for i in range(knight.h):
            for j in range(knight.w):
                knight_map[knight.x + i][knight.y + j] = knight.id
                if knight_id != attk_id and maps[knight.x + i][knight.y + j] == 1:
                    knight.life -= 1
                    knight.damage += 1

        if knight.life <= 0:
            del knight_dict[knight_id]

            for i in range(knight.h):
                for j in range(knight.w):
                    knight_map[knight.x + i][knight.y + j] = 0

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

# Main
L, N, Q = map(int, sys.stdin.readline().split())
knight_dict = {}
maps = []  # 벽 정보
knight_map = [[0] * L for _ in range(L)]
op_list = []  # 명령 정보
dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]]  # 위 오 아 왼

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

# get knight
for i in range(1, N + 1):
    r, c, h, w, k = map(int, sys.stdin.readline().split())
    knight = Knight(i, r - 1, c - 1, h, w, k)
    knight_dict[i] = knight

    for j in range(h):
        for l in range(w):
            knight_map[knight.x + j][knight.y + l] = knight.id

# get operation
for _ in range(Q):
    op_list.append(map(int, sys.stdin.readline().split()))

# game
for op in op_list:
    move_knight(op)

total = 0
for knight in knight_dict.values():
    total += knight.damage
print(total)
profile
반박 시 여러분의 말이 맞습니다.

0개의 댓글