📜  水滴问题

📅  最后修改于: 2021-10-25 09:13:56             🧑  作者: Mango

考虑长度为 L 的管子。管子内的 N 个不同位置有 N 个水滴。每个水滴都以不同的速度向管道末端移动(x=L)。当一个水滴与另一个水滴混合时,它假定与它混合的水滴的速度。确定从管道末端出来的液滴数量。
参考下图:

圆圈上的数字表示水滴的速度

问题

例子:

Input: length = 12, position = [10, 8, 0, 5, 3], 
       speed = [2, 4, 1, 1, 3]
Output: 3
Explanation:
Droplets starting at x=10 and x=8 become a droplet, 
meeting each other at x=12 at time =1 sec.
The droplet starting at 0 doesn't mix with any 
other droplet, so it is a drop by itself.
Droplets starting at x=5 and x=3 become a single 
drop, mixing with each other at x=6 at time = 1 sec.
Note that no other droplets meet these drops before 
the end of the pipe, so the answer is 3.
Refer to the figure below
Numbers on circles indicates speed of water droplets.

演练

方法:
这个问题使用贪心技术。
如果满足两个条件,一滴将与另一滴混合:
1. 如果液滴比它混合的液滴快
2. 如果较快下降的位置在较慢下降的后面。

我们使用一组对来存储位置和第 i下降到达管道末端所需的时间。然后我们根据水滴的位置对数组进行排序。现在我们对哪些水滴位于哪些水滴后面以及它们各自到达终点所需的时间有了清晰的了解。更多的时间意味着更少的速度,更少的时间意味着更快的速度。现在,较慢下降之前的所有下降都将与其混合。在较慢的下降之后的所有下降与下一个较慢的下降混合等等。
例如到达终点的次数为:12、3、7、8、1(按位置排序)
第 0 滴最慢,不会与下一滴混合
第一滴比第二滴快,所以它们会混合,第二滴比第三滴快,所以三滴会混合在一起。它们不能与第 4 滴混合,因为它更快。
局部最大值的数量 + 残留物(最后一个局部最大值之后的下降)= 下降的总数。

下面是上述方法的实现:

C++
#include 
using namespace std;
 
// Function to find the number
// of the drops that come out of the
// pipe
int drops(int length, int position[],
          int speed[], int n)
{   
    // stores position and time
    // taken by a single
    // drop to reach the end as a pair
    vector > m(n);
 
    int i;
    for (i = 0; i < n; i++) {
 
        // calculates distance needs to be
        // covered by the ith drop
        int p = length - position[i];
 
        // inserts initial position of the
        // ith drop to the pair 
        m[i].first = position[i];
 
        // inserts time taken by ith
        // drop to reach
        // the end to the pair
        m[i].second = p * 1.0 / speed[i];
    }
 
    // sorts the pair according to increasing
    // order of their positions
    sort(m.begin(), m.end());
    int k = 0; // counter for no of final drops
 
 
    int curr_max = m[n-1].second;
    // we traverse the array demo
    // right to left
    // to determine the slower drop
    for (i = n - 2; i >= 0; i--)
    {
        // checks for next slower drop
        if (m[i].second > curr_max)
        {
            k++;
              curr_max=m[i].second;
        }
    }
 
    // calculating residual
    // drops in the pipe
    k++;
    return k;
}
 
// Driver Code
int main()
{
    // length of pipe
    int length = 12;
   
    // position of droplets
    int position[] = { 10, 8, 0, 5, 3 };
   
    // speed of each droplets
    int speed[] = { 2, 4, 1, 1, 3 };
    int n = sizeof(speed)/sizeof(speed[0]);
    cout << drops(length, position, speed, n);
    return 0;
}


Python3
# Function to find the number
# of the drops that come out of the
# pipe
def drops(length, position, speed, n):
     
    # Stores position and time
    # taken by a single drop to
    # reach the end as a pair
    m = []
 
    for i in range(n):
         
        # Calculates distance needs to be
        # covered by the ith drop
        p = length - position[i]
 
        # Inserts initial position of the
        # ith drop to the pair
        # inserts time taken by ith
        # drop to reach
        # the end to the pair
        m.append([position[i], (p * 1.0) / speed[i]])
 
    # Sorts the pair according to increasing
    # order of their positions
    m.sort()
     
    # Counter for no of final drops
    k = 0
     
    curr_max = m[n - 1][1]
     
    # We traverse the array demo
    # right to left
    # to determine the slower drop
    for i in range(n - 2, -1, -1):
         
        # Checks for next slower drop
        if (m[i][1] > curr_max):
            k += 1
            curr_max = m[i][1]
             
    # Calculating residual
    # drops in the pipe
    k += 1
    return k
     
# Driver Code
 
# Length of pipe
length = 12
 
# Position of droplets
position = [ 10, 8, 0, 5, 3 ]
 
# Speed of each droplets
speed = [ 2, 4, 1, 1, 3 ]
n = len(speed)
 
print(drops(length, position, speed, n))
 
# This code is contributed by divyeshrabadiya07


C#
using System;
using System.Collections.Generic;
class GFG
{
 
  // Function to find the number
  // of the drops that come out of the
  // pipe
  static int drops(int length, int[] position,
                   int[] speed, int n)
  {
 
    // stores position and time
    // taken by a single
    // drop to reach the end as a pair
    List> m = new List>();
    int i;
    for (i = 0; i < n; i++)
    {
 
      // calculates distance needs to be
      // covered by the ith drop
      int p = length - position[i];
 
      // inserts initial position of the
      // ith drop to the pair
      // inserts time taken by ith
      // drop to reach
      // the end to the pair
      m.Add(new Tuple(position[i], p * 1.0 / speed[i]));
    }
 
    // sorts the pair according to increasing
    // order of their positions
    m.Sort();
    int k = 0; // counter for no of final drops
    int curr_max = (int)m[n - 1].Item2;
 
    // we traverse the array demo
    // right to left
    // to determine the slower drop
    for (i = n - 2; i >= 0; i--)
    {
 
      // checks for next slower drop
      if (m[i].Item2 > curr_max)
      {
        k++;
        curr_max = (int)m[i].Item2;
      }
    }
 
    // calculating residual
    // drops in the pipe
    k++;
    return k;
  }
 
  // Driver code
  static void Main()
  {
 
    // length of pipe
    int length = 12;
 
    // position of droplets
    int[] position = { 10, 8, 0, 5, 3 };
 
    // speed of each droplets
    int[] speed = { 2, 4, 1, 1, 3 };
    int n = speed.Length;
    Console.WriteLine(drops(length, position, speed, n));
  }
}
 
// This code is contributed by divyesh072019


Javascript


输出
3