跳转至

573. 松鼠模拟 🔒

题目描述

给你两个整数 heightwidth ,代表一个大小为 height x width 的花园。你还得到了以下信息:

  • 一个数组 tree ,其中 tree = [treer, treec] 是花园中树的位置,
  • 一个数组 squirrel ,其中 squirrel = [squirrelr, squirrelc] 是花园中松鼠的位置,
  • 一个数组 nuts ,其中 nuts[i] = [nutir, nutic] 是花园中第 ith 个坚果的位置。

松鼠一次最多只能携带一个坚果,并且能够向上、下、左、右四个方向移动到相邻的单元格。

返回松鼠收集所有坚果并逐一放在树下的 最小距离

距离 是指移动的次数。

 

示例 1:

输入:height = 5, width = 7, tree = [2,2], squirrel = [4,4], nuts = [[3,0], [2,5]]
输出:12
解释:为实现最小的距离,松鼠应该先摘 [2, 5] 位置的坚果。

示例 2:

输入:height = 1, width = 3, tree = [0,1], squirrel = [0,0], nuts = [[0,2]]
输出:3

 

提示:

  • 1 <= height, width <= 100
  • tree.length == 2
  • squirrel.length == 2
  • 1 <= nuts.length <= 5000
  • nuts[i].length == 2
  • 0 <= treer, squirrelr, nutir <= height
  • 0 <= treec, squirrelc, nutic <= width

解法

方法一:路径分析

我们观察松鼠的移动路径,可以发现,松鼠会首先移动到某个坚果的位置,然后移动到树的位置。接下来,松鼠的移动路径之和等于“其余坚果到树的位置之和”再乘以 $2$。

因此,我们只需要选出一个坚果,作为松鼠的第一个目标,使得其到树的位置之和最小,即可得到最小路径。

时间复杂度 $O(n)$,空间复杂度 $O(1)$。其中 $n$ 为坚果的数量。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class Solution:
    def minDistance(
        self,
        height: int,
        width: int,
        tree: List[int],
        squirrel: List[int],
        nuts: List[List[int]],
    ) -> int:
        x, y, a, b = *tree, *squirrel
        s = sum(abs(i - x) + abs(j - y) for i, j in nuts) * 2
        ans = inf
        for i, j in nuts:
            c = abs(i - x) + abs(j - y)
            d = abs(i - a) + abs(j - b) + c
            ans = min(ans, s + d - c * 2)
        return ans
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
    public int minDistance(int height, int width, int[] tree, int[] squirrel, int[][] nuts) {
        int ans = Integer.MAX_VALUE;
        int s = 0;
        for (int[] a : nuts) {
            s += f(a, tree);
        }
        s *= 2;
        for (int[] a : nuts) {
            int c = f(a, tree);
            int d = f(a, squirrel) + c;
            ans = Math.min(ans, s + d - c * 2);
        }
        return ans;
    }

    private int f(int[] a, int[] b) {
        return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
    }
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class Solution {
public:
    int minDistance(int height, int width, vector<int>& tree, vector<int>& squirrel, vector<vector<int>>& nuts) {
        int ans = INT_MAX;
        int s = 0;
        for (auto& a : nuts) {
            s += f(a, tree);
        }
        s *= 2;
        for (auto& a : nuts) {
            int c = f(a, tree);
            int d = f(a, squirrel) + c;
            ans = min(ans, s + d - c * 2);
        }
        return ans;
    }

    int f(vector<int>& a, vector<int>& b) {
        return abs(a[0] - b[0]) + abs(a[1] - b[1]);
    }
};
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
func minDistance(height int, width int, tree []int, squirrel []int, nuts [][]int) int {
    f := func(a, b []int) int {
        return abs(a[0]-b[0]) + abs(a[1]-b[1])
    }
    ans := math.MaxInt32
    s := 0
    for _, a := range nuts {
        s += f(a, tree)
    }
    s *= 2
    for _, a := range nuts {
        c := f(a, tree)
        d := f(a, squirrel) + c
        ans = min(ans, s+d-c*2)
    }
    return ans
}

func abs(x int) int {
    if x < 0 {
        return -x
    }
    return x
}

评论