[LeetCode] 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.

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.

这道题是关于可爱的小松鼠的题目,不由得让人想起来冰河世纪里面的那只对粟子执着追求的原始松鼠。每天在校园里也能见到抱着粟子啃的小家伙,有的挺个大白肚皮,吃的巨肥,完全没有天敌啊。本题说有一只小松鼠,一堆在不同位置的粟子,还有一棵树,小松鼠目标是把所有的粟子都运到树的位置,问怎样的顺序可以使用最少的步数。那么我们这么想,如果小松鼠本身就在树的位置,那么把所有的栗子运回树的步数就是一个定值,为每个粟子距树的距离总和乘以2。那么只有当小松鼠不在树的位置时候,它首先要走到一个粟子的位置,然后再去树那儿。而且一旦小松鼠到了树那,再出发,之后的步数就是定值了。所以关键就在于决定小松鼠首先去哪个粟子那。博主最开始犯了一个这道题很容易犯的一个错误,就是在选起始粟子的时候的判定条件是松鼠到该粟子的距离加上该粟子到树的距离之和最小当作判定条件,其实这样是不对的。举个简单的反例,比如此时有两个粟子A和B,小松鼠到粟子A的距离为2,粟子A到树的距离为1,小松鼠到粟子B的距离为2,粟子B到树的距离为2。那么按照博主之前的选择方法,会选先去粟子A,因为小松鼠到粟子A再到树的距离之和为3,小于先去粟子B再去树的距离之和(为4)。然而小松鼠先去粟子A的话,总距离就是7,而如果先去粟子B的话,总距离为6,这就说明之前的判定条件不对。那么正确思路应该是,假设小松树最先应该去粟子i,那么我们假设粟子i到树的距离为x,小松鼠到粟子i的距离为y,那么如果小松鼠不去粟子i,累加步数就是2x,如果小松鼠去粟子i,累加步数就是x+y,我们希望x+y尽可能的小于2x,那么就是y尽可能小于x,即x-y越大越好。这样我们遍历每个粟子,找出x-y最大的那个,让小松鼠先去捡就好了。话说萌萌的小松鼠真是很可爱,希望这些小萌物们远离马路,不要随便过马路,真是太危险了。。。 

public:
    int minDistance(int height, int width, vector<int>& tree, vector<int>& squirrel, vector<vector<int>>& nuts) {
        int res = 0, mxDiff = INT_MIN, idx = 0;
        for (auto nut : nuts) {
            int dist = abs(tree[0] - nut[0]) + abs(tree[1] - nut[1]);
            res += 2 * dist;
            mxDiff = max(mxDiff, dist - abs(squirrel[0] - nut[0]) - abs(squirrel[1] - nut[1]));
        }
        return res - mxDiff;
    }
};

参考资料:

https://discuss.leetcode.com/topic/88490/java-5-liner-o-nuts-time-o-1-space

本文转自博客园Grandyang的博客,原文链接:[LeetCode] Squirrel Simulation 松鼠模拟

,如需转载请自行联系原博主。

相关文章
|
存储 C++
【 LeetCode 热题 HOT 100】2. 两数相加 (C++ 链表 模拟)
【 LeetCode 热题 HOT 100】2. 两数相加 (C++ 链表 模拟)
156 0
【 LeetCode 热题 HOT 100】2. 两数相加 (C++ 链表 模拟)
【LeetCode剑指offer57 II】和为s的连续正数序列(用vector模拟滑动窗口)
因为找的是连续子序列(并且题目的原序列是从小到大元素排列)的和为target,所以使用滑动窗口,如果加上当前元素后sum满足条件则push_back
129 0
【LeetCode剑指offer57 II】和为s的连续正数序列(用vector模拟滑动窗口)
|
算法
[leetcode] 最长公共前缀 简单水题模拟
根据数据范围来说,我们可以枚举最长公共前缀的长度,长度的范围是[0, minLen(strs)] 然后一边枚举长度一边判断是否成功即可 还有一种就是将判断是否满足公共前缀写成check函数,然后用二分的方法来得到最长的前缀长度 题目很水 Code:
108 0
[leetcode] 最长公共前缀 简单水题模拟
|
算法
[leetcode] 复数乘法 基础模拟
[leetcode] 复数乘法 基础模拟
104 0
[leetcode] 复数乘法 基础模拟
|
算法
[leetcode] 球会落何处 模拟
给出一个矩阵,里面的值为-1 or 1 -1的时候是从左上到右下,1的时候是从左下到右上 当一个球从上方x(0 < x < m)放入之后,从哪个出口掉落还是无法从出口掉落 能通过的情况为: / / 即某条线为’/’,其左边的线也是’/’,箭头所指为当前斜线 {\ } ↑ \ \ 即当前线为’’,其右边的线也是’’,箭头所指为当前斜线 {}↑ 但是还要注意边界问题
105 0
[leetcode] 球会落何处 模拟
|
机器学习/深度学习 算法
【刷穿 LeetCode】检测「环形数组是否存在循环」的三种方式:「朴素模拟」&「遍历标记(含优化)」
【刷穿 LeetCode】检测「环形数组是否存在循环」的三种方式:「朴素模拟」&「遍历标记(含优化)」
|
机器人 C++
LeetCode 2069. 模拟行走机器人 II(模拟)
LeetCode 2069. 模拟行走机器人 II(模拟)
172 0
LeetCode 2069. 模拟行走机器人 II(模拟)
|
2月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行