N
: 체스판의 크기 ()
K
: 말의 개수 ()
chess_info
: 체스판의 정보
horse_info
: 말의 정보
크기가 N×N인 체스판에서 K개의 말로 게임을 진행했을 때 게임이 종료되는 턴의 번호를 출력하는 문제이다.
⭐️ 게임 방법
- 체스판 위에 말 K개 놓고 시작
- 이동 방향 미리 정해져 있음
- 4가지 중 하나 (위, 아래, 왼쪽, 오른쪽)
- 체스판 정보
- 칸의 색 의미 : 0은 흰색, 1은 빨간색, 2는 파란색
- 흰색 → 이동하는 칸에 말이 이미 있으면 맨 위에 놓기
- 빨간색 → 모든 말의 쌓인 순서 반대로 바꿈
- 파란색 → 이동하는 말의 이동 방향 반대로하고 한 칸 이동, 이동하려는 칸이 파란색이면 이동 ❌
- 체스판 벗어나는 경우 = 파란색과 같은 경우
- 말 정보 (3개의 정수)
- 행 번호 : 1부터 시작
- 열 번호 : 1부터 시작
- 이동 방향 : 1은 →, 2는 ←, 3은 ↑, 4는 ↓
- 턴 1번
- 1~K번 말 모두 순서대로 이동시키기
- 한 말 이동 시 위의 말도 함께 이동
- 게임 종료
- 턴 진행 중 말이 4개 쌓이는 순간 종료
- 출력
- 게임 종료되는 턴 번호
- 번호가 1000보다 크거나 절대 종료 안되면
-1
→ 과정이 매우 복잡하므로 말을 움직이는 함수를 따로 구현한다.
말 정보 입력받기
말 이동 함수
말 이동하며 턴 수 세기
체스판 입력 →
턴 수 1000번까지 K개의 말 이동하며 함수 수행 →
최종 시간복잡도
로,최악의 경우 이 되어 제한 시간 0.5초 내에 연산이 가능하다.
1000번 반복하면서 함수 수행
# 말의 정보 입력
horse_info = []
...
for i in range(K):
...
# 수정 전
horse_info[i] = [row-1, col-1, dir-1]
# 수정 후
horse_info.append([row-1, col-1, dir-1])
dir = (dir + 2) % 4
라는 수식을 먼저 썼는데 항상 옳은 값을 반환하지 않았다.dir = (dir + 1) % 2 + (dir // 2) * 2
로 수정했다.import sys
input = sys.stdin.readline
# N, K 입력
N, K = map(int, input().split())
# 체스판 정보 입력
chess_info = [list(map(int, input().split())) for _ in range(N)]
# 체스판 말 위치 저장
horse_loc = [[[] for _ in range(N)] for _ in range(N)]
# 말의 정보 입력
horse_info = []
for i in range(K):
row, col, dir = map(int, input().split())
# 리스트에 추가
horse_info.append([row-1, col-1, dir-1])
# 체스판에 말 위치 저장
horse_loc[row-1][col-1].append(i)
# 4가지 이동 방향 정의 (0 : 오른쪽, 1 : 왼쪽, 2 : 위, 3 : 아래)
moves = [(0, 1), (0, -1), (-1, 0), (1, 0)]
# 말 이동 함수 구현
def move_horse(i):
x, y, dir = horse_info[i]
# 이동
nx, ny = x + moves[dir][0], y + moves[dir][1]
# 범위 밖이거나 파란색인지 확인
if not (0 <= nx < N and 0 <= ny < N) or chess_info[nx][ny] == 2:
# 방향 전환 후 업데이트
dir = (dir + 1) % 2 + (dir // 2) * 2 # 방향 반대로
horse_info[i][2] = dir
# 다음 한칸 진행
nx, ny = x + moves[dir][0], y + moves[dir][1]
# 다시 확인
if not (0 <= nx < N and 0 <= ny < N) or chess_info[nx][ny] == 2:
return 0
# 같은 곳에 있는 말 모두 꺼내기
idx = horse_loc[x][y].index(i) # 이동할 말 인덱스 뽑아서
move_together = horse_loc[x][y][idx:] # 말이 이동할 때 위에 있는 말들도 같이 이동
horse_loc[x][y] = horse_loc[x][y][:idx]
# 흰색이면 말 추가
if chess_info[nx][ny] == 0:
horse_loc[nx][ny].extend(move_together)
# 빨간색일 경우 쌓인 순서 반대
if chess_info[nx][ny] == 1:
horse_loc[nx][ny].extend(move_together[::-1])
# 말 위치 업데이트
for h in move_together:
horse_info[h][0] = nx
horse_info[h][1] = ny
# 쌓인 말 4개면 종료
if len(horse_loc[nx][ny]) >= 4:
return 1
return 0
# 결과 출력
turn = 1
while turn <= 1000:
for i in range(K):
flag = move_horse(i)
if flag:
print(turn)
sys.exit()
turn += 1
print(-1)