1. 程式人生 > >[LeetCode] Squirrel Simulation 松鼠模擬

[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 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最大的那個,讓小松鼠先去撿就好了。話說萌萌的小松鼠真是很可愛,希望這些小萌物們遠離馬路,不要隨便過馬路,真是太危險了。。。

class Solution {
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;
    }
};

參考資料: