링크: www.acmicpc.net/problem/17837
문제:
재현이는 주변을 살펴보던 중 체스판과 말을 이용해서 새로운 게임을 만들기로 했다. 새로운 게임은 크기가 N×N인 체스판에서 진행되고, 사용하는 말의 개수는 K개이다. 말은 원판모양이고, 하나의 말 위에 다른 말을 올릴 수 있다. 체스판의 각 칸은 흰색, 빨간색, 파란색 중 하나로 색칠되어있다.
게임은 체스판 위에 말 K개를 놓고 시작한다. 말은 1번부터 K번까지 번호가 매겨져 있고, 이동 방향도 미리 정해져 있다. 이동 방향은 위, 아래, 왼쪽, 오른쪽 4가지 중 하나이다.
턴 한 번은 1번 말부터 K번 말까지 순서대로 이동시키는 것이다. 한 말이 이동할 때 위에 올려져 있는 말도 함께 이동한다. 말의 이동 방향에 있는 칸에 따라서 말의 이동이 다르며 아래와 같다. 턴이 진행되던 중에 말이 4개 이상 쌓이는 순간 게임이 종료된다.
- A번 말이 이동하려는 칸이
- 흰색인 경우에는 그 칸으로 이동한다. 이동하려는 칸에 말이 이미 있는 경우에는 가장 위에 A번 말을 올려놓는다.
- A번 말의 위에 다른 말이 있는 경우에는 A번 말과 위에 있는 모든 말이 이동한다.
- 예를 들어, A, B, C로 쌓여있고, 이동하려는 칸에 D, E가 있는 경우에는 A번 말이 이동한 후에는 D, E, A, B, C가 된다.
- 빨간색인 경우에는 이동한 후에 A번 말과 그 위에 있는 모든 말의 쌓여있는 순서를 반대로 바꾼다.
- A, B, C가 이동하고, 이동하려는 칸에 말이 없는 경우에는 C, B, A가 된다.
- A, D, F, G가 이동하고, 이동하려는 칸에 말이 E, C, B로 있는 경우에는 E, C, B, G, F, D, A가 된다.
- 파란색인 경우에는 A번 말의 이동 방향을 반대로 하고 한 칸 이동한다. 방향을 반대로 바꾼 후에 이동하려는 칸이 파란색인 경우에는 이동하지 않고 가만히 있는다.
- 체스판을 벗어나는 경우에는 파란색과 같은 경우이다.
- 흰색인 경우에는 그 칸으로 이동한다. 이동하려는 칸에 말이 이미 있는 경우에는 가장 위에 A번 말을 올려놓는다.
체스판의 크기와 말의 위치, 이동 방향이 모두 주어졌을 때, 게임이 종료되는 턴의 번호를 구해보자.
코드:
import sys
input = sys.stdin.readline
def game(n, k, chess_color, chess_horse, horse):
count = 1
while count < 1000:
for i in range(k):
r, c, d = horse[i]
nr, nc = r + dr[d], c + dc[d]
if not (0 <= nr < n and 0 <= nc < n) or chess_color[nr][nc] == 2:
d ^= 1
nr, nc = r + dr[d], c + dc[d]
if not (0 <= nr < n and 0 <= nc < n) or chess_color[nr][nc] == 2:
nr, nc = r, c
horse[i] = [nr, nc, d]
if nr == r and nc == c:
continue
j = chess_horse[r][c].index(i)
for m in chess_horse[r][c][j+1:]:
horse[m][0], horse[m][1] = nr, nc
if not chess_color[nr][nc]:
chess_horse[nr][nc] += chess_horse[r][c][j:]
elif chess_color[nr][nc] == 1:
chess_horse[nr][nc] += chess_horse[r][c][j:][::-1]
chess_horse[r][c] = chess_horse[r][c][:j]
if len(chess_horse[nr][nc]) > 3:
return count
count += 1
return -1
n, k = map(int, input().split())
dr, dc = [0, 0, -1, 1], [1, -1, 0, 0]
chess_color = [list(map(int, input().split())) for _ in range(n)]
chess_horse = [[[] * n for _ in range(n)] for _ in range(n)]
horse = []
for i in range(k):
r, c, d = map(lambda x: int(x)-1, input().split())
horse.append([r, c, d])
chess_horse[r][c].append(i)
print(game(n, k, chess_color, chess_horse, horse))
내 머리가 나쁜건지 문제가 어려운건지 고민하다가, 역시 문제가 어려워서 잘 안풀리는거라고 나를 위로하며 풀었던 문제다. 처음에 대략적인 코드를 작성하는데는 시간이 오래걸리지 않았는데, 테스트 케이스 5번에서 계속 걸려서 도대체 뭐가 문제인가 고민했다. 그리고 내가 실질적 문맹이었다는 것을 깨달았다.
말이 이동한다는게
- A번 말의 위에 다른 말이 있는 경우에는 A번 말과 위에 있는 모든 말이 이동한다.
A번 말과 '위에 있는 모든 말'이 이동을 하는 거다. 나는 계속 A번 말이 위치한 칸의 모든 말을 이동시켜주고 있었다..
위에 있는 말만 이동하도록 수정하니 성공했다.
'Algorithm > Python' 카테고리의 다른 글
[파이썬/프로그래머스][3차]파일명 정렬 (0) | 2021.04.09 |
---|---|
[파이썬/프로그래머스][3차] n진수 게임 (0) | 2021.04.09 |
[파이썬/백준 17142]연구소 3/ BFS (0) | 2021.04.07 |
[python/leetcode]cheapest flights within k stops/dijkstra (0) | 2021.04.07 |
[python/leetcode]employee importance/dfs (0) | 2021.04.07 |