573. Squirrel Simulation(Medium)

来源:互联网 发布:iphone本地阅读软件 编辑:程序博客网 时间:2024/05/16 16:51

原题目:
  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 : 5Width : 7Tree position : [2,2]Squirrel : [4,4]Nuts : [[3,0], [2,5]]Output: 12Explanation:

例
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.

题目大意如下:
  在2D的一个表格里面,给定一个树的坐标,一只松树的坐标还有其他很多坚果的坐标,要求求出这只松鼠一个一个把坚果收集到树下所需要的总的步数。
  注:
  1.松鼠一次只能搬运一个坚果
  2.每次只能向四个方向(前后左右)中的一个,移动一步;

解题思路:
  我们设松鼠从初始点搬运第一个坚果到树下这个距离为d。
  不难发现,除了松鼠搬运第一个坚果外,搬运其他坚果时都是一个过程:树->坚果->树,这个过程是无法改变的,并且来回距离都一样,所以我们需要考虑的只有d。
  怎样设置d的值才能使总步数到最小呢?
  
  以例1为例:
  
  有[3,0], [2,5]两个坚果,松鼠坐标为[4,4],树的坐标为[2,2]。
  
  我们可以注意到,从松鼠到坚果再到树的距离s_to_t:
  对于第一个坚果:s_to_t=4-3+4-0=5;
  对于第二个坚果:s_to_t=4-2+5-4=3。
  
  然而,树->坚果->树这个距离double_t:
  对于第一个坚果:double_t=2*(3-2+2-0)=6;
  对于第二个坚果:double_t=2*(2-2+5-2)=6。

  通过对比我们可以发现,我们第一次应该取第二个坚果,即d=3。因为6-3>6-5,设first_try = double_t - s_to_t,这是一个亏损的量,这个亏损量越大说明我们越应该把它对应s_to_t的设置为d,因为设置为d可以减少步数,否则我们的步数就会越多。

代码如下:

class Solution {public:    int minDistance(int height, int width, vector<int>& tree, vector<int>& squirrel, vector<vector<int>>& nuts) {        int f_cost = INT_MIN , mark = 0 , total_step = 0 ;        int first_try = 0 , s_to_t , double_t , first_step ;        for(int i = 0 ; i < nuts.size() ; ++i){            s_to_t =  abs(nuts[i][0] - squirrel[0]) + abs(nuts[i][1] - squirrel[1])                       + abs(tree[0] - nuts[i][0]) + abs(tree[1] - nuts[i][1]) ;            double_t = 2*(abs(tree[0] - nuts[i][0]) + abs(tree[1] - nuts[i][1])) ;            first_try = double_t - s_to_t ;            if(first_try > f_cost){                first_step = s_to_t ;                f_cost = first_try ;                mark = i ;            }        }        total_step += first_step ;        for(int i = 0 ; i < nuts.size() ; ++i)            if(i != mark) total_step += 2*(abs(tree[0] - nuts[i][0]) + abs(tree[1] - nuts[i][1])) ;        return total_step ;    }};

算法分析:
  算出d需要线性,加上总步数也是线性,所以总时间复杂度为O(n)。

0 0
原创粉丝点击