마법사 상어와 파이어볼

  • 2차원 ArrayList를 이용하는 것은 나무 재테크와 비슷하고, 파이어볼이 이동하는 것은 낚시왕과 매우 유사하다!!!

  • 이 문제는 전체 질량의 합을 구하는 문제이기 때문에 전체 질량의 합이 가감되고 변화하는 것을 처리하는 부분이 핵심이고, 정말 정말 정말 제일 중요하다!⭐️⭐️⭐️⭐️⭐️

  • 파이어볼이 새로 이동하는 위치를 tempList에 저장하고, tempList에 저장된 새로운 위치를 원래 Map에 저장한다. 그리고 Map에 저장된 Map[i][j]마다 크기가 2이상인지 판단해서 연산처리. 따라서 이동할 때마다 tempList를 초기화해서 이동하는 위치를 저장해야한다!!!!!(2번째 풀었을 때 틀린 이유)

생각하지 못한 부분 or 빼먹은 부분

  1. 문제 조건에서 1번행과 N번 행은 연결되어있고, 1번열과 N번 열은 연결되어있다.⭐️⭐️⭐️ => 이동할 칸수를 모듈러 연산자를 이용해 나눗셈처리해줘야한다! ex) NxN = 3x3 = 9칸 짜리 지도에서 이동할 칸이 10칸이고 현재 0번째 칸이 있다고 하자. 그러면 0부터 10칸을 이동한다면 0->1,1->2,2->3,3->4,...이렇게 해서 최종 이동할 칸은 인덱스가 10인 10번째 칸이다. 하지만 첫번째행/열과 마지막 행/열이 연결되어있기 때문에 (현재위치+이동할칸 수) % (첫행~마지막행 수) 이렇게 모듈러 연산을 이용하면 나머지가 최종 이동하는 인덱스가 된다!

  2. 1번 조건에 의해 현재 N = 4, 4 x4인 지도의 0번째 행에서 위로 1칸 이동한다면 이동할 칸은 else if 문을 따라 이해해보면 nx = 4- (|-1| % 4) = 4 - (1 % 4) = 밑에서 나머지 값만큼 이동하는 것이다!! 그러니까, 0번째 행과 N-1번째행이 연결되어 있기 때문에 이동할 칸이 0보다 작거나 N-1보다 클 때(범위를 벗어날 때) 규칙성을 찾고, 나머지 연산을 적절히 이용해서 점화식으로 나타낼 수 있어야 한다!!!(낚시왕과 거의 정확하게 동일함!!!)

    if(nx >= N) {
    	nx = nx % N;
    } else if(nx < 0) {
    	nx = N-(Math.abs(nx) % N);
    }
  3. 잘못 생각한 부분 : 0번째 행/열 N-1번째 행/열에서 범위가 벗어나는 경우는 파이어볼이 사라진다고 생ㅇ각했다. 하지만 1번 조건에 의해 이것은 낚시왕에서 상어가 이동하는 것처럼 이동한다. 즉, 0번째에서 음수로 초과하는 경우, N-1번째 행에서 거슬러 올라가고, N-1번째에서 양수로 초과하는 경우 0번째 행에서 다시 내려가는 것이다!!!

    => N 을 주기로 위치가 반복된다! 그렇기 때문에 N으로 나누어서 나머지 연산만큼 0에서 더해주거난, N에서 빼주면 된다!!!!!!

    아래는 행을 기준으로 했지만 열 기준도 마찬가지다. ① nx < 0 : 이동할 행 계산해보니 음수인 경우! : 연결되있기 때문에 밑(N-1)부터 이동하는 처리 ex) N = 4, 현재 위치 0, 윗방향 이동, 이동할 칸=3, 이동할 위치 = -3 => 이동할 위치 즉, 초과되는 만큼 N을 주기로 반복되기 때문에 나머지값만큼 밑에서 이동한다! => 일단 이동할 위치값(초과되는 정도)이 음수기 때문에 절댓값 처리해주고, 초과하는 만큼 N으로 나눈 나머지 값만큼 N에서 빼주면 된다! ② nx > N-1 : 이동할 행 계산해 보니 양수인 경우! : 연결되있기 때문에 위(0)부터 이동하는 처리 ex) N = 4, 현재 위치 3(N-1), 이동할 칸=3, 이동할 위치 = 6> N-1(3) =>이동할 위치(초과되는 정도)를 N으로 나누고 난 후 나머지만큼 위에서부터 이동한다! =>nx = nx % N => 나머지 연산만큼 0에서부터 이동하기 때문에 나머지 값 그자체만으로 최종이동하는 행 인덱스가 된다!

  4. 4개의 파이어볼로 분화할 때 전체 질량 변화(전체 질량이 정답이 되기 때문에, 4개의 파이어볼로 분화할 때 전체 질량을 어떻게 처리하는지가 제일 가장 중요하다!!!!!⭐️⭐️⭐️⭐️⭐️) 처음에 생각했을 때, 전체 질량합을 tot이라고 한다면 Map[i][j] 리스트에 2개 이상의 파이어볼이 있다면 tot=0으로 초기화하고, tot = newM*4 로 생각했다. 하지만 이것은 틀렸다! 왜냐하면 초기의 경우에만 한 칸에 모든 파이어볼들이 전부 들어가있지만, 대다수의 다른 경우들은 Map[i][j] 가 아닌 다른 위치에 한칸에 하나의 파이어볼들이 있을 수 있다! 그렇기 때문에 tot를 0으로 만들어버리면 안 되고, tot에서 분화할 Map[i][j] 리스트의 파이어볼들의 질량합 만큼 빼주고 나서, 4개의 새로 생겨난 파이어볼의 질량합만큼 tot에 다시 더해주면 된다! (분화한 파이어볼의 질량인 newM*4 만큼 더해주면 되는 것이다!)

  5. (Java 문법) List 컬렉션의 removeAll()과 clear() 비교 : clear()가 더 빠르다고 한다!? https://app.gitbook.com/@heunnajo/s/java/collection-framework/list-removeall-clear

  6. Map[i][j] 리스트의 k번째 파이어볼을 삭제 후 k를 1씩 감소시키는 이유!⭐️⭐️⭐️⭐️⭐️ k=0부터 시작해서 Map[i][j]의 크기 만큼 반복해서 k번째 파이어볼을 이동시킨 후, 삭제한다! 그렇기 때문에 k=0 번째 요소를 삭제한 후 1번째 요소를 삭제하려 할 때, Map[i][j] 리스트의 크기가 1감소되고, 이미 0번째 요소가 삭제된 후기 때문에 삭제하려는 요소는 0번째가 된다! 따라서 k가 리스트 크기만큼 증가하는 for문을 돌 때, k=0에서 k=1로 증가하기 전에 1을 감소시켜줌으로써 k는 0으로 유지되면서 리스트의 첫번째 요소들을 삭제할 수 있는 것이다!

Last updated