문제출처: https://school.programmers.co.kr/learn/courses/30/lessons/92345
정리
22년도 카카오 채용 마지막 문제였다.
이전에 체스게임을 만든 적이 있는데 그때 사용한 알고리즘이 "민맥스 알고리즘"이다. 발판게임도 마찬가지로 "민맥스 알고리즘"을 활용하여 푸는 문제였다.
나는 체스게임을 만들면서 많이 공부하고 느꼈던 점도 많았지만 이번 문제를 보면서 비슷한 발상조차 하지 못해서 아직 부족하다는 생각이 들게하는 문제였다.
다른 사람들의 코드를 보면서도 느낀 점이 정말 많고 주석이나 이번 포스트를 쓰면서 많이 정리된 것 같다.
풀이
본 풀이는 먼저 질문게시판의 힌트를 활용하여 구현에 성공한 뒤 다른 사람들의 풀이들을 참고하며 리팩터링하였다.😂
코드
def solution(board, aloc, bloc):
n,m = len(board),len(board[0])
directions = [(1,0),(-1,0),(0,1),(0,-1)]
# Out Of Boundary
def OOB(x,y):
return x<0 or x>=n or y<0 or y>=m
# 재귀함수의 방문여부를 체크
global g_vis
g_vis = [[0]*m for _ in range(n)]
# 승리할 경우 남은 이동거리는 짝수이고 패배할 경우는 홀수이다.
def dfs(curx,cury,opx,opy):
global g_vis
# 예를들어 플레이어 A와 플레이어 B가 같은 칸에 있을 때 플레이어 A가 이동을 했다면
# vis[curx][cury] = 0 -> vis[curx][cury] = 1
# 즉, 플레이어 B 차례에서 vis[curx][cury] == 1일 경우 패배한다.
if g_vis[curx][cury]:
return 0
ret = 0
for d in directions:
nx,ny = curx+d[0],cury+d[1]
if OOB(nx,ny) or board[nx][ny]==0 or g_vis[nx][ny]:
continue
# 방문
g_vis[curx][cury] = 1
# 턴이 넘어가면서 다음 (curx,cury)는 현재의 (opx,opy)
res = dfs(opx,opy,nx,ny)+1
# 방문해제
g_vis[curx][cury] = 0
# ret : 패배한 경우의 수 res : 승리한 경우의 수 >> 갱신
if ret%2==0 and res%2==1:
ret = res
# ret : 패배한 경우의 수 res : 패배한 경우의 수 >> 둘 중 큰값
elif ret%2==0 and res%2==0:
ret = max(res,ret)
# ret : 승리한 경우의 수 res : 승리한 경우의 수 >> 둘 중 작은값
elif ret%2==1 and res%2==1:
ret = min(res,ret)
# ret : 승리 res : 패배 >> 갱신 X
return ret
return dfs(aloc[0],aloc[1],bloc[0],bloc[1])