[Silver III] 킹 - 1063
성능 요약
메모리: 108384 KB, 시간: 92 ms
분류
구현, 시뮬레이션
제출 일자
2025년 2월 25일 20:11:39
문제 설명
8*8크기의 체스판에 왕이 하나 있다. 킹의 현재 위치가 주어진다. 체스판에서 말의 위치는 다음과 같이 주어진다. 알파벳 하나와 숫자 하나로 이루어져 있는데, 알파벳은 열을 상징하고, 숫자는 행을 상징한다. 열은 가장 왼쪽 열이 A이고, 가장 오른쪽 열이 H까지 이고, 행은 가장 아래가 1이고 가장 위가 8이다. 예를 들어, 왼쪽 아래 코너는 A1이고, 그 오른쪽 칸은 B1이다.
킹은 다음과 같이 움직일 수 있다.
- R : 한 칸 오른쪽으로
- L : 한 칸 왼쪽으로
- B : 한 칸 아래로
- T : 한 칸 위로
- RT : 오른쪽 위 대각선으로
- LT : 왼쪽 위 대각선으로
- RB : 오른쪽 아래 대각선으로
- LB : 왼쪽 아래 대각선으로
체스판에는 돌이 하나 있는데, 돌과 같은 곳으로 이동할 때는, 돌을 킹이 움직인 방향과 같은 방향으로 한 칸 이동시킨다. 아래 그림을 참고하자.
입력으로 킹이 어떻게 움직여야 하는지 주어진다. 입력으로 주어진 대로 움직여서 킹이나 돌이 체스판 밖으로 나갈 경우에는 그 이동은 건너 뛰고 다음 이동을 한다.
킹과 돌의 마지막 위치를 구하는 프로그램을 작성하시오.
입력
첫째 줄에 킹의 위치, 돌의 위치, 움직이는 횟수 N이 주어진다. 둘째 줄부터 N개의 줄에는 킹이 어떻게 움직여야 하는지 주어진다. N은 50보다 작거나 같은 자연수이고, 움직이는 정보는 위에 쓰여 있는 8가지 중 하나이다.
출력
첫째 줄에 킹의 마지막 위치, 둘째 줄에 돌의 마지막 위치를 출력한다.
풀이
def valid(i, j) :
return 0 <= i < 8 and 0 <= j < 8
def sol_1063() :
move = {
'R' : (1, 0), # 한 칸 오른쪽으로
'L' : (-1, 0), # 한 칸 왼쪽으로
'B' : (0, -1), # 한 칸 아래로
'T' : (0, 1), # 한 칸 위로
'RT' : (1, 1), # 오른쪽 위 대각선으로
'LT' : (-1, 1), # 왼쪽 위 대각선으로
'RB' : (1, -1), # 오른쪽 아래 대각선으로
'LB' : (-1, -1) # 왼쪽 아래 대각선으로
}
king, stone, N = input().split()
king = list(king)
stone = list(stone)
king[0] = ord(king[0]) - ord('A')
king[1] = int(king[1]) - 1
stone[0] = ord(stone[0]) - ord('A')
stone[1] = int(stone[1]) - 1
# print(ord('A')) # 65
N = int(N)
for _ in range(N) :
moving = input().rstrip()
ci, cj = king
ni, nj = ci + move[moving][0], cj + move[moving][1]
if valid(ni, nj) :
if [ni, nj] == stone and valid(stone[0] + move[moving][0], stone[1] + move[moving][1]):
king = [ni, nj]
stone = [ni + move[moving][0], nj + move[moving][1]]
elif [ni, nj] != stone :
king = [ni, nj]
elif not valid(stone[0] + 1, stone[1] + 1) :
continue
king = [chr(king[0] + 65), int(king[1]) + 1]
stone = [chr(stone[0] + 65), int(stone[1]) + 1]
print(''.join(map(str, king)))
print(''.join(map(str, stone)))
sol_1063()
이 문제를 여러 방면에서 접근할 수 있겠지만, 나는 그래프로 접근하기 보다는 좌표로 접근을 하였다. 이때 중요한 점은 움직이는 체스판의 규격을 잘 생각하는 것이다. 사실 여기서 오류를 많이 범했다.
- valid(i, j) : 체스판 안에 있는지에 대해서 묻는 함수이다.
- move : 문제에 있는 움직이는걸 복사해와서 붙여넣은 다음 딕셔너리 형태로 만들었다. 이때, 접근을 좌표로 하기로 마음먹었기 때문에 정수로 다 치환해 줄 것이며, 이를 위해 좌표 이동 역시 정수로 할 생각이다.
여기서 문제점은 평소 그래프는 좌상단이 0, 0 인데, 문제에서 제시한 체스판 사진을 보면 좌하단이 A1이다. - king, stone, N : 입력받는 값
- king : 체스말 king이다. move 대로 움직이는 주체이다. 여기서 king의 좌표를 A1 => (0, 0)으로 바꿀 것이며, 이때 0, 0은 통상 그래프에서 사용하는 좌상단이 아니라 좌하단이라는 점을 명심해야한다.
- stone : king의 움직이는 곳에 stone이 있으면, stone과 king이 같이 움직이는 돌이다.
- 나는 이때 king과 stone의 좌표를 A1, A2 에서 (0, 0), (0, 1) 로 바꿔서 계산할 것이다. 이를 활용하는 것은 ord와 chr를 활용하였다. 해당 방법은 코드를 참고.
- 이동 : moving을 입력받고, move[moving]을 받아온다. 이는 흔히 사용되는 di, dj 가 될것이고 king의 좌표에 더해준다.
- 제한 사항 : (ni, nj)가 체스판 위에 있는지 (valid 함수 안에서 True를 리턴하는지), (ni, nj)의 자리에 stone이 있고 이 stone이 체스판 위에 있는지 판별하고, 조건에 부합하면 이동을 진행한다.
- 마지막으로 다시 A1, A2와 같은 좌표로 변환시키면 문제는 쉽게 해결할 수 있다.
전형적인 구현 문제로 오랜만에 재밌게 풀어보았다.
'알고리즘 스터디' 카테고리의 다른 글
[백준/파이썬][Silver I] 데스 나이트 - 16948 (0) | 2025.03.06 |
---|---|
[백준/파이썬][Bronze I] Claustrophobic Cows - 6003 (0) | 2025.03.06 |
[백준/파이썬][Silver V] Code Guessing - 24586 (0) | 2025.02.24 |
[백준/파이썬][Gold IV] Organizing Beads - 23178 (0) | 2025.02.19 |
[백준/파이썬][Gold V] Growling Gears - 10325 (0) | 2025.02.19 |