코드트리 - 술래잡기 (Python)

Kim Yongbin·2024년 10월 15일
0

코딩테스트

목록 보기
153/162
import sys

# Solution
class Catcher:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.dir_idx = 0
        self.move = 0
        self.di = 1
        self.move_idx = 0
        self.move_length_list = []

    def get_dir(self):
        dirs = [[-1, 0], [0, 1], [1, 0], [0, -1]]
        return dirs[self.dir_idx]

    def change_dir(self):
        curr = self.move_length_list[self.move_idx]

        if curr == self.move:
            if self.x == 0 and self.y == 0 or self.x == n // 2 and self.y == n //2:
                self.di *= -1
                self.dir_idx = (self.dir_idx + 2) % 4
            else:
                self.move_idx += self.di
                self.dir_idx = (self.dir_idx + self.di) % 4
            self.move = 0

class Runner:
    def __init__(self, idx, x, y, type):
        self.idx = idx
        self.x = x
        self.y = y
        self.type = type
        self.dir = [0, 1] if type == 1 else [1, 0]

        self.change_dir()

    def change_dir(self):
        nx = self.x + self.dir[0]
        ny = self.y + self.dir[1]
        if not in_range(nx, ny):
            self.dir[0] *= -1
            self.dir[1] *= -1

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

# Step 1: Move Runner
def move_runners():
    for runner in runner_dict.values():
        if in_range_3(runner, catcher):
            dir = runner.dir
            nx = runner.x + dir[0]
            ny = runner.y + dir[1]

            if catcher.x != nx or catcher.y != ny:
                runner_map[runner.x][runner.y].remove(runner.idx)
                runner.x = nx
                runner.y = ny
                runner_map[runner.x][runner.y].append(runner.idx)

            runner.change_dir()

# Step 2: Move Catcher
def move_catcher():
    dx, dy = catcher.get_dir()
    catcher.x += dx
    catcher.y += dy

    catcher.move += 1
    catcher.change_dir()

# Step 3: Catch
def catch():
    cnt = 0
    dx, dy = catcher.get_dir()
    for i in range(3):
        fx = catcher.x + dx * i
        fy = catcher.y + dy * i

        if in_range(fx, fy) and tree_map[fx][fy] == 1:
            continue

        if in_range(fx, fy) and len(runner_map[fx][fy]) > 0:
            cnt += len(runner_map[fx][fy])

            for idx in runner_map[fx][fy]:
                runner_dict.pop(idx)

            runner_map[fx][fy] = []

    return cnt

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

def in_range_3(runner, catcher):
    return abs(runner.x - catcher.x) + abs(runner.y - catcher.y) <= 3

# main
n, m, h, k = map(int, sys.stdin.readline().split())

# set catcher
catcher = Catcher(n // 2, n // 2)
catcher_move_length_list = []
for i in range(1, n):
    catcher_move_length_list.extend([i, i])
catcher_move_length_list.append(n - 1)
catcher.move_length_list = catcher_move_length_list

# set runner
runner_map = [[[] for _ in range(n)] for _ in range(n)]
runner_dict = {}
for i in range(1, m + 1):
    x, y, type = map(int, sys.stdin.readline().split())
    runner = Runner(i, x - 1, y - 1, type)
    runner_dict[i] = runner
    runner_map[x - 1][y - 1].append(runner.idx)

# set tree
tree_map = [[0] * n for _ in range(n)]
for _ in range(h):
    x, y = map(int, sys.stdin.readline().split())
    tree_map[x - 1][y - 1] = 1

# game
score = 0
for i in range(1, k + 1):
    move_runners()
    move_catcher()
    catch_cnt = catch()
    score += i * catch_cnt
print(score)
profile
반박 시 여러분의 말이 맞습니다.

0개의 댓글