Week6 홍금비 1600 말이되고픈원숭이 풀이 (2차원 배열만을 가지고 품) #146
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
풀이
이 문제의 핵심은 이러합니다.
1. 2차원 int[][]map에 방문한 좌표값에 ' 말처럼 이동 할 수 있는 남은 횟수'를 저장하여 방문처리를 하는 것입니다.
2. 큐에 들어가는 총 이동 횟수는 (Info.move) 항상 1........2..............3 이렇게 오름차순으로 들어갈 수 밖에없습니다. 따라서 도착지점의 좌표값이라면 그때의 큐에서 꺼낸 이동 횟수가 최소 움직임 (정답값) 일 수 밖에 없습니다.
2번에 대해서 먼저 설명해보겠습니다.
저는 제 풀이에서
로 따로 class를 만들어 bfs 큐에 값을 넣었습니다.
처음 시작 좌표 (0,0)에 있었다면
Info (r= 0, c = 0, hores= K ,move = 0) 일 겁니다.
여기서 원숭이는 4방(상하좌우)로 이동하거나 8방(체스의 나이트 처럼) 으로 총 12방향으로 이동 할 수 있습니다. (8방은 남은 횟수가 존재한다는 가정하에 얘기임)
이 차례에서 큐에 들어가는 값들은 모두 한번의 동작으로 움직인거기때문에 move =1인 상태로 들어가게됩니다.
그럼 또 큐에서 move=1인 Info를꺼내와 4방,8방의 경우를 모두 해준다면 이 차례에서 들어가는 값은 move =2일 겁니다.
여기서 큐에 특성상 앞에 move =1인 경우가 먼처 처음으로 들어와있기때문에 move=1인 값들이 먼저 처리가 되주어야 move=2인 경우를 따지게 됩니다. 따라서 원숭이가 도착지에 도착할 수 있는 경우에 move값이 최소 동작이 될 수 밖에 없습니다.
그렇다면 이제 방문 처리를 해주어야합니다. 방문 처리를 해주지 않는다면 방문한 좌표를 계속 방문하게 되는 무한 루프 상태에 걸리게 될테니까요.
한 번 방문한 좌표에 다시 들어 갈 수 없게끔 처리하면 되지않나? 왜냐면 처음 방문했을때 move 값이 가장 최소일꺼니까 ! 라고 생각하고 처리해버린다면 안됩니다.
아래의 코드를 설명해보면
if(map[nr][nc]<curHourse)한번 방문한 좌표는 다시 들어오지않게 처리하는 것이 아닌, map[nr][nc] (nr,nc까지 오는데 남은 말 횟수) 가 curHourse ( 어떤 다른 경로로 또 왔을때 남은 말횟수) 보다 작다면 한 번 더 다시 방문을 해주어야합니다.
그 이유는 예를들어 map[3][2]에 = 2(남은 말 횟수) 라는 값으로 처음 값이 찍혔을때 map[3][2]에 = 2 이 경우에서 다음 좌표로 이동하는 경우들이 또 생겨 나게 되는데 이 경우들이 도착지(정답)에 도착한다는 보장이 없기때문입니다. 따라서 nr =3 , nc=2, 일때 curHourse 가 4라고 한다면 전에 저장되어있는 값 2 보다 4가 훨씬 더 많은 경로로 이동하여 탐색 할 수 있기때문에 (map[nr][nc]<curHourse) 라는 조건으로 방문 처리를 해주어야합니다.
이런식으로 탐색하게 되었을때 도착지에 도착한다면 그때까지 이동한 횟수의 값이 가장 최소이기때문에 그 값을 정답으로 해주면 됩니다.
** 생각해볼만한 점**
저는 처음에 Queue를 선언했을때 LinkedList로 선언하였습니다. 그런데 메모가 9만 정도 , 시간은 600ms 정도 나왔습니다.
여기서 Queue를 ArrayDeque로 선언하니 메모리는 5만대 , 시간은 488ms 가 나왔습니다. 메모리 부분에서 엄청 차이가 난다는걸
볼 수 있습니다.
따라서 Queue를 LinkedList로 선언했을때와 ArrayDeque로 선언했을 때 차이점을 한번 알아보신다면 좋을 거같아 링크 몇개 남겨 두겠습니다.
리뷰 요청 사항
느낀점