문제
플레이어는 GameJam에 참가했다. GameJam은 현장에서 즉석으로 팀을 꾸려 게임의 규칙을 만든 뒤, 생각한 규칙을 코드로 옮겨서 게임을 만들어내는 대회이다.
플레이어가 속한 팀은 보드로 즐길 수 있는 간단한 보드게임을 만들었다. 게임의 진행 방법과 규칙은 다음과 같다.
- 게임은 한 변의 길이가 $N$인 격자 보드 위에서 진행한다. 보드는 한 변의 길이가 $1$인 $N^2$개의 칸으로 나누어져 있다.
- 각 칸에는 <command> 에 해당하는 방향으로 <count> 칸만큼 한 칸씩 이동하라는 지시가 적혀있다.
- 플레이하는 사람은 처음에 보드의 칸 중 하나에 말을 올려놓는다.
- 각 칸에 적힌 지시대로 말을 이동한다. 만약 이동 중에 보드 밖으로 나가게 된다면 반대쪽의 첫 번째 칸으로 이동한다.
예를 들어 맨 오른쪽 칸에서 오른쪽으로 이동해야 한다면 해당 행의 맨 왼쪽 칸으로 이동하고, 맨 아래 칸에서 아래쪽으로 이동해야 한다면 해당 열의 맨 위쪽 칸으로 이동하고, 이동 거리가 남아 있다면 계속 이동한다. - 만약 이동하다가 자신의 말이 이미 한 번이라도 방문한 칸을 다시 지나야 할 경우에는 게임이 종료된다. 그 외의 경우에는 게임이 종료될 때까지 위의 4번 단계를 반복한다.
- 게임의 점수는 시작한 칸을 포함하여, 게임이 종료되기 전까지 말이 방문한 서로 다른 칸의 개수이다.
플레이어는 GameJam의 최종 발표 때 게임을 시연해 보기 위해, 구름이와 미리 연습 게임을 진행해 보려고 한다. 플레이어와 구름이가 각각의 게임에서 처음에 말을 올려둔 칸이 주어졌을 때, 두 사람 중 누가 더 높은 점수를 획득했는지를 구해보자. 단 플레이어와 구름이는 별개의 게임이다.
입력
첫째 줄에 격자 보드의 크기 $N$이 주어진다.
둘째 줄에는 구름이가 말을 올려둔 칸의 좌표 $R_g, C_g$가 공백을 두고 주어진다. 보드의 $R_g$번째 행, $C_g$번째 열에 말을 올려두었다는 뜻이다.
셋째 줄에는 플레이어가 말을 올려둔 칸의 좌표 $R_p, C_p$가 공백을 두고 주어진다. 보드의 $R_p$번째 행, $C_p$번째 열에 말을 올려두었다는 뜻이다.
다음 $N$개의 줄에는 보드의 각 칸에 적혀있는 지시 사항이 주어진다. 각 줄마다 $N$개의 지시 사항이 <count><command> 형식으로 공백을 두고 주어지고, $i$번째 줄에서 $j$번째로 주어지는 지시 사항은 보드의 $r$번째 행, $c$번째 열의 정보를 의미한다. <count> 는 이동 횟수, <command> 는 이동 방향을 말한다.
- $3 \leq N \leq 200$
- $1 \leq R_g, C_g, R_p, C_p \leq N$
- <count> 는 $1$이상 $N$이하의 정수이다.
- <command> 는 U, D, R, L 중 하나이다. 각각 위쪽, 아래쪽, 오른쪽, 왼쪽을 의미한다. 이 문제에서 위쪽은 행 번호가 감소하는 방향이다.
- 입력에서 주어지는 모든 수는 정수이다.
출력
구름이가 게임에서 승리하면 goorm 과 구름이가 얻은 점수를 공백을 두고 출력하고, 플레이어가 승리하면 player 와 플레이어가 얻은 점수를 공백을 두고 출력한다. 두 사람이 비기는 테스트 케이스는 주어지지 않는다.
문제 접근 방식
주어진 그대로 구현하면 되는 전형적인 시뮬레이션, 구현 류의 문제다.
칸을 넘어갈 때 주의해서 구현해야 된다. 이를 구현하기 위해 나머지 연산을 이용하면 된다.
또한, 입력에서 <count>가 두 자리 수가 될 수 있음에 명심하자.
이를 유의하지 않고 한 자리 수로 생각하여 구현하면 의문의 틀렸습니다를 받을 수 있다.
정답 코드
# GameJam
import sys
input = sys.stdin.readline
N = int(input())
R_g, C_g = map(lambda x: int(x)-1, input().rstrip().split())
R_p, C_p = map(lambda x: int(x)-1, input().rstrip().split())
matrix = [input().rstrip().split() for _ in range(N)]
groom = [[0 for _ in range(N)] for _ in range(N)]
flag_g = True
groom[R_g][C_g] = 1
groom_cnt = 1
while flag_g:
count, command = int(matrix[R_g][C_g][:-1]), matrix[R_g][C_g][-1]
if command == 'U':
for _ in range(count):
R_g -= 1
R_g %= N
if groom[R_g][C_g] == 0:
groom[R_g][C_g] = 1
groom_cnt += 1
else:
flag_g = False
break
elif command == 'D':
for _ in range(count):
R_g += 1
R_g %= N
if groom[R_g][C_g] == 0:
groom[R_g][C_g] = 1
groom_cnt += 1
else:
flag_g = False
break
elif command == 'R':
for _ in range(count):
C_g += 1
C_g %= N
if groom[R_g][C_g] == 0:
groom[R_g][C_g] = 1
groom_cnt += 1
else:
flag_g = False
break
else:
for _ in range(count):
C_g -= 1
C_g %= N
if groom[R_g][C_g] == 0:
groom[R_g][C_g] = 1
groom_cnt += 1
else:
flag_g = False
break
player = [[0 for _ in range(N)] for _ in range(N)]
flag_p = True
player[R_p][C_p] = 1
player_cnt = 1
while flag_p:
count, command = int(matrix[R_p][C_p][:-1]), matrix[R_p][C_p][-1]
if command == 'U':
for _ in range(count):
R_p -= 1
R_p %= N
if player[R_p][C_p] == 0:
player[R_p][C_p] = 1
player_cnt += 1
else:
flag_p = False
break
elif command == 'D':
for _ in range(count):
R_p += 1
R_p %= N
if player[R_p][C_p] == 0:
player[R_p][C_p] = 1
player_cnt += 1
else:
flag_p = False
break
elif command == 'R':
for _ in range(count):
C_p += 1
C_p %= N
if player[R_p][C_p] == 0:
player[R_p][C_p] = 1
player_cnt += 1
else:
flag_p = False
break
else:
for _ in range(count):
C_p -= 1
C_p %= N
if player[R_p][C_p] == 0:
player[R_p][C_p] = 1
player_cnt += 1
else:
flag_p = False
break
if player_cnt < groom_cnt:
print(f'goorm {groom_cnt}')
else:
print(f'player {player_cnt}')
특별히 배운 점
함수로 구현했더라면 조금 더 깔끔하게 구현할 수도 있었을 것 같다.
생각나는대로 코드를 작성해서 그런가 코드가 썩 보기 좋지는 않다.
'알고리즘 > 구름톤 챌린지' 카테고리의 다른 글
[구름톤 챌린지] 3주차 12일차 발전기 (0) | 2023.08.30 |
---|---|
[구름톤 챌린지] 3주차 11일차 통증 (2) (0) | 2023.08.29 |
[구름톤 챌린지] 2주차 9일차 폭탄 구현하기 (2) (0) | 2023.08.24 |
[구름톤 챌린지] 2주차 8일차 통증 (0) | 2023.08.24 |
[구름톤 챌린지] 2주차 7일차 구름 찾기 깃발 (0) | 2023.08.23 |