본문 바로가기

Algorithm

[leetcode] 573. Squirrel Simulation

There's a tree, a squirrel, and several nuts. Positions are represented by the cells in a 2D grid. Your goal is to find the

minimal

distance for the squirrel to collect all the nuts and put them under the tree one by one. The squirrel can only take at most

one nut

at one time and can move in four directions - up, down, left and right, to the adjacent cell. The distance is represented by the number of moves.

Example 1:

Input: Height : 5 Width : 7 Tree position : [2,2] Squirrel : [4,4] Nuts : [[3,0], [2,5]] Output: 12 Explanation:

Note:

  1. All given positions won't overlap.
  2. The squirrel can take at most one nut at one time.
  3. The given positions of nuts have no order.
  4. Height and width are positive integers. 3 <= height * width <= 10,000.
  5. The given positions contain at least one nut, only one tree and one squirrel.

 

 

다람쥐가 도토리를 주어다가 나무에 가져다 놓는 경로를 찾는 문제였다. 다람쥐는 한번에 하나씩의 도토리만을 가져다가 나무에 놓아둘 수 있다.

 

언뜻 문제를 보면 BFS 문제라고 생각하기 쉬운데, 조금 생각해보면 찾고자 하는 경로가 도토리의 개수에 따라 엄청 많아질 수 있음을 알 수 있다.

 

나무로 왔다갔다 하는 왕복 행동이 도토리 하나당 한번씩 일어남을 알 수 있는데, 단 한가지의 예외는 다람쥐가 처음 위치에서 도토리를 주우러 가는 경우이다. 위 그림의 1번처럼 맨 처음에 다람쥐가 어느 도토리로 향하느냐가 최단거리를 완성하게 된다.

 

그렇다면 다람쥐는 처음에 주울 도토리를 어떤 도토리를 선택을 해야 할까? 처음엔 가장 가까운 도토리를 찾으러 가면 될것이라고 생각했지만, 다람쥐가 가장 가까운 도토리로 가더라도 나무에서의 그 도토리까지의 위치가 더 가깝다면, 다람쥐는 다른 도토리를 찾아야 한다. (최단 경로를 위해서)

 

즉, 다람쥐가 맨처음에 향해야 할 도토리는 도토리 ↔ 나무 사이의 거리보다 도토리 ↔ 다람쥐 사이의 거리가 가까워야 의미가 있으며 이 거리가 최대로 차이나는 도토리가 바로 다람쥐가 맨 처음 찾아야 할 도토리이다.

 

public class SquirrelSimulation {
	public int minDistance(int height, int width, int[] tree, int[] squirrel, int[][] nuts) {
		int totalDistance = 0;
		int maxDiff = 0;
		int nutPos = 0;

		for (int i = 0 ; i < nuts.length ; i++) {
			int [] nut = nuts[i];

			int distanceFromTree = (Math.abs(tree[0] - nut[0]) + Math.abs(tree[1] - nut[1]));
			int distanceFromSquirrel = (Math.abs(squirrel[0] - nut[0]) + Math.abs(squirrel[1] - nut[1]));
			totalDistance += (distanceFromTree * 2);

			if (maxDiff <= distanceFromTree - distanceFromSquirrel) {
				nutPos = i;
				maxDiff = distanceFromTree - distanceFromSquirrel;
			}
		}

		totalDistance -= (Math.abs(tree[0] - nuts[nutPos][0]) + Math.abs(tree[1] - nuts[nutPos][1]));
		totalDistance += (Math.abs(squirrel[0] - nuts[nutPos][0]) + Math.abs(squirrel[1] - nuts[nutPos][1]));

		return totalDistance;
	}

	public static void main(String[] args) {
		int [] tree = {3,2};
		int [] squirrel = {0,1};
		int [][] nuts = {{2,0},{4,1},{0,4},{1,3},{1,0},{3,4},{3,0},{2,3},{0,2},{0,0},{2,2},{4,2},{3,3},{4,4},{4,0},{4,3},{3,1},{2,1},{1,4},{2,4}};

		SquirrelSimulation squirrelSimulation = new SquirrelSimulation();
		System.out.println(squirrelSimulation.minDistance(5, 5, tree, squirrel, nuts));

	}
}