Category
프로그래밍  PS

[백준 / python] 17780: 새로운 게임

2024년 12월 13일 by Hwang

문제

https://www.acmicpc.net/problem/17780

입력

첫째 줄에 체스판의 크기 N, 말의 개수 K가 주어진다. 둘째 줄부터 N개의 줄에 체스판의 정보가 주어진다. 체스판의 정보는 정수로 이루어져 있고, 각 정수는 칸의 색을 의미한다. 0은 흰색, 1은 빨간색, 2는 파란색이다.

다음 K개의 줄에 말의 정보가 1번 말부터 순서대로 주어진다. 말의 정보는 세 개의 정수로 이루어져 있고, 순서대로 행, 열의 번호, 이동 방향이다. 행과 열의 번호는 1부터 시작하고, 이동 방향은 4보다 작거나 같은 자연수이고 1부터 순서대로 →, ←, ↑, ↓의 의미를 갖는다.

같은 칸에 말이 두 개 이상 있는 경우는 입력으로 주어지지 않는다.

출력

게임이 종료되는 턴의 번호를 출력한다. 그 값이 1,000보다 크거나 절대로 게임이 종료되지 않는 경우에는 -1을 출력한다.


풀이

구현 문제

import sys
from collections import deque

dirs = ((0, 0), (0, 1), (0, -1), (-1, 0), (1, 0))
N, K = map(int, sys.stdin.readline().split())
board_info = [[2] * (N + 2) for _ in range(N + 2)]
board = [[0] * (N + 2) for _ in range(N + 2)]
total_queue = [deque([n]) for n in range(K + 1)]
queue_pos = [(0, 0)]
unit_queue, unit_dir = [0], [0]

for r in range(N):
    row = map(int, sys.stdin.readline().strip().split())
    for c, v in enumerate(row):
        board_info[r + 1][c + 1] = v

for i in range(1, K + 1):
    r, c, d = map(int, sys.stdin.readline().split())
    queue_pos.append((r, c))
    unit_dir.append(d)
    unit_queue.append(i)
    board[r][c] = i

# 말 쌓기. 만약 말이 4 개이상 쌓인다면 출력 후 프로그램 종료
def move_units(frm, to, reverse=False):
    cur = total_queue[frm]
    nxt = total_queue[to]
    if len(cur) + len(nxt) >= 4:
        print(attempt)
        exit()
    while cur:
        unit = cur.popleft() if not reverse else cur.pop()
        unit_queue[unit] = to
        nxt.append(unit)

def move_unit(unit):
    cur_queue_index = unit_queue[unit]
    cur_r, cur_c = queue_pos[cur_queue_index]

    if total_queue[cur_queue_index][0] != unit:
        return

    new_r, new_c = cur_r + dirs[unit_dir[unit]][0], cur_c + dirs[unit_dir[unit]][1]
    cur_queue = board[cur_r][cur_c]
    other_queue = board[new_r][new_c]

    if board_info[new_r][new_c] == 0:  # 흰색
        board[cur_r][cur_c] = 0
        if other_queue != 0:
            move_units(cur_queue, other_queue)
            return
        board[new_r][new_c] = cur_queue
        queue_pos[cur_queue] = (new_r, new_c)

    elif board_info[new_r][new_c] == 1:  # 빨간색
        board[cur_r][cur_c] = 0
        if other_queue != 0:
            move_units(cur_queue, other_queue, True)
            return
        total_queue[cur_queue].reverse()
        board[new_r][new_c] = cur_queue
        queue_pos[cur_queue] = (new_r, new_c)

    elif board_info[new_r][new_c] == 2:  # 파란색
        new_dir = unit_dir[unit] + 1 if unit_dir[unit] % 2 == 1 else unit_dir[unit] - 1
        new_r, new_c = cur_r + dirs[new_dir][0], cur_c + dirs[new_dir][1]
        unit_dir[unit] = new_dir
        if board_info[new_r][new_c] == 2:
            return
        move_unit(unit)

attempt = 1
while attempt <= 1000:
    for i in range(1, K + 1):
        move_unit(i)
    attempt += 1
print(-1)


 Comment