문제 출처 : https://www.acmicpc.net/problem/2178
한 한시간 정도 걸려서 풀은 것 같다... (이것도 장족의 발전입니다ㅜㅜ)
불과 두달 전만 해도 알고리즘 자체에 대해서도 전무후무 그냥 문자열? 관련 문제들 같은것만 풀고 간단한 구현문제들만 시도했는데 나름 그래도 이제 구박사님의 도움없이 알고리즘을 스스로 짤 수 있다는 것에 스스로에게 박수를 보낸다 하핫 ( 물론 기초적인 문제지만... )
BFS를 이용하자고 결정. ( 이유는 뒤에 )
1. BOARD위에 나의 위치를 기반으로 동서남북, 모든 방향을 탐색하자
-> 처음에는 INDEX를 그냥 변수로 직접 줄라했느데 반복되는 코드 라인들이 보여서 dic이라는 방향 변수를 이용하여 for문으로 처리해줬다.
2. 지나간 곳은 VISITED 처리를 해줘야 한다 ( 여기서 잠깐! 과연 지나간 길을 다시 지나가면서 최단 거리일 수 있을까? 결과는 불가능. )
-> 그래서 지나간 자리는 이동할 수 없는 0과 같은 취급을 하여 0으로 변경해준다.
3. 목적지에 도착하면 if문으로 종료시킨다...될까?
-> BFS니까, height( 이동한 거리 ) 단위로 그래프를 탐색하니까 결국 최단 거리로 이동하여 목적지에 도달했을 때 가장 빨리 도착한다.
3단계에서 약간 실수가 있었다. 위치(pos)가 바뀔때마다 처음에는 count를 해줬는데 이렇게 될 경우
결과는 1->3->F 로 3이 되어야 하는데 1->2->3->F로 4가 되버린다.
그렇기 때문에 트리에서의 HEIGHT의 개념을 바탕으로 여기에 이동한 거리라는 걸 적용시킨다. 이를 구현하기 위해 tmp (해당 height에 있는 node의 수 ), next_tmp( next height에 있는 node의 수 ), height라는 변수를 도입하여 한 height에 있는 node를 조회할 때마다 next_tmp에 값을 추가해주고 que에서 tmp만큼 pop된다면 해당 height의 모든 node들을 조회했다 판단. tmp=next_tmp로 해주고 height+1을 해주어 다음 height로 넘어간다.
어떤 최단 경로, 특수한 경로를 구할 때는 DFS보다 BFS가 훨씬 유리하다. 그 이유를 대략적으로 짐작해보면 이렇지 않을까? DFS로 구현할 경우 해당 경로가 아니라면 다시 다른 경로를 탐색하고 문제의 경우까지 모두 탐색을 해야하다보니 '통상적으로' 시간 복잡도가 커지게 되는 것이다.
import sys
from collections import deque
N,M = list(map(int,sys.stdin.readline().rstrip("\n").split()))
board = [[0 for f in range(M+2)]]+[[0]+list(map(int,sys.stdin.readline().rstrip("\n")))+[0] for m in range(N)]+[[0 for l in range(M+2)]]
h,w = 1,1
pos = deque([[h,w]])
board[pos[0][0]][pos[0][1]]=0
dic = [[0,1],[1,0],[0,-1],[-1,0]]
height, tmp, next_tmp = 0, 1, 0
while pos :
#동,남,서,북
now=pos.popleft()
tmp-=1
if (now[0]==N) and (now[1]==M) :
print(height+1)
break
#코드 동일 recycle
#결국 몇번째 height냐 => 정답
for i in range(4) : # 0,1,2,3
if board[now[0]+dic[i][0]][now[1]+dic[i][1]] == 1 :
pos.append([now[0]+dic[i][0],now[1]+dic[i][1]])
board[now[0]+dic[i][0]][now[1]+dic[i][1]]=0
next_tmp+=1
if tmp==0 :
tmp = next_tmp
next_tmp = 0
height+=1
결과는 맞았지만 실행시간이 다른 사람들에 비해 평균적으로 더 오래 걸리기 때문에 과연 어떻게 푸는 게 더 효율적인가 공부해보자.
! 혼자 공부를 위해 참고하고자 적어놧지만 문제가 된다면 삭제하겠습니다.