Open In App

Minimum Time to travel from Source to Destination

Last Updated : 14 Jan, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given a source point (x1, y1) and a destination point (x2, y2). Find the minimum time to travel from (x1, y1) to (x2, y2) if the speed is v1 for every point with y < 0 and v2 for every point with y > 0.
Note: The answer should be correct up to 6 decimal places.

Example:

Input: x1 = 3, y1 = -20, x2 = 3, y2 = 25, v1 = 40, v2 = 5
Output: 5.500000
Explanation: We can move from (3, -20) to (3, 0) in time = 20/40 = 0.5 and then from (3, 0) to (3, 25) in time = 25/5 = 5, so total time will be 0.5 + 5 = 5.500000

Input: x1 = -5, y1 = -10, x2 = 8, y2 = 15, v1 = 20, v2 = 6
Output: 3.256763

Approach: The problem can be solved using the following approach:

The observation for approaching this problem lies in understanding the behavior of the speeds (v1 and v2) for point with y < 0 and y > 0, respectively. Since the speeds are constant for each region, the critical points to consider are where the speeds change, i.e., where y = 0

By recognizing this, one can intuitively divide the problem into two parts: the time to travel from the source to y=0 and the time to travel from y=0 to the destination. For each part, the speed is constant, allowing for straightforward calculations.

Ternary search is then used to efficiently find the x-coordinate where the transition between the two speed regions occurs. This transition point minimizes the total travel time, considering the different speeds on either side of y=0. The iterative narrowing down of the x-coordinate range helps converge to the optimal solution.

In summary, the key observation is to focus on the transition point at y=0 and use it to minimize the total travel time by employing ternary search on the x-coordinate range.

Steps to solve the problem:

  • Create a function getDistance() to calculate the distance between two points using the distance formula.
  • Create a function getTime() to calculate the time to travel from one point to another based on the distance and speed.
  • Ternary Search:
    • Initialize lo as min(x1, x2) and hi = max(x1, x2).
    • Use a while loop to perform ternary search until the x-coordinate range becomes sufficiently small.
    • Inside the loop:
      • Calculate mid1 and mid2 within the current range.
      • Calculate the times f1 and f2 using the getTime() function.
      • Adjust the search range based on the comparison of f1 and f2.
      • Update the minimum time (res).
  • Print the minimum time (res) with the precision up to 6 decimal places.

Below is the implementation of the above approach:

C++




#include <bits/stdc++.h>
#define INF 1e9
using namespace std;
 
typedef long long ll;
 
// Function to calculate the distance between two points
double getDistance(double x1, double y1, double x2,
                   double y2, double v)
{
    double dx = x1 - x2;
    double dy = y1 - y2;
    return sqrt(dx * dx + dy * dy) / v;
}
 
// Function to calculate the total time for the given
// yCrossingPoint
double getTime(double yCrossingPoint, double x1, double y1,
               double x2, double y2, double v1, double v2)
{
    // Calculate the distance traveled for each segment and
    // return the total time
    return getDistance(x1, y1, yCrossingPoint, 0, v1)
           + getDistance(yCrossingPoint, 0, x2, y2, v2);
}
 
int main()
{
    int x1 = 3, y1 = -20, x2 = 3, y2 = 25, v1 = 40, v2 = 5;
 
    // Ensure x1 <= x2
    if (x1 > x2)
        swap(x1, x2);
 
    // Initialize the minimum time variable
    double res = INF;
    double lo = x1, hi = x2;
 
    // Ternary Search to find the minimum time
    while (lo <= hi) {
        if (lo == hi) {
            // Update the minimum time if lo and hi are
            // equal
            res = min(res,
                      getTime(lo, x1, y1, x2, y2, v1, v2));
            break;
        }
 
        // Calculate midpoints for ternary search
        double mid1 = lo + (hi - lo) / 3.0;
        double mid2 = hi - (hi - lo) / 3.0;
 
        // Calculate times for midpoints
        double f1 = getTime(mid1, x1, y1, x2, y2, v1, v2);
        double f2 = getTime(mid2, x1, y1, x2, y2, v1, v2);
 
        // Adjust the search range based on comparisons
        if (f1 > f2) {
            res = min(res, f2);
            lo = mid1 + 1;
        }
        else if (f1 < f2) {
            res = min(res, f1);
            hi = mid2 - 1;
        }
        else {
            res = min(res, f1);
            lo = mid1 + 1;
            hi = mid2 - 1;
        }
    }
    // Output the result with the desired precision
    cout << setprecision(6) << fixed << res << endl;
    return 0;
}


Java




import java.util.Scanner;
 
public class TernarySearch {
 
    // Function to calculate the distance between two points
    static double getDistance(double x1, double y1, double x2,
                              double y2, double v) {
        double dx = x1 - x2;
        double dy = y1 - y2;
        return Math.sqrt(dx * dx + dy * dy) / v;
    }
 
    // Function to calculate the total time for the given
    // yCrossingPoint
    static double getTime(double yCrossingPoint, double x1, double y1,
                          double x2, double y2, double v1, double v2) {
        // Calculate the distance traveled for each segment and
        // return the total time
        return getDistance(x1, y1, yCrossingPoint, 0, v1)
                + getDistance(yCrossingPoint, 0, x2, y2, v2);
    }
 
    public static void main(String[] args) {
        int x1 = 3, y1 = -20, x2 = 3, y2 = 25, v1 = 40, v2 = 5;
 
        // Ensure x1 <= x2
        if (x1 > x2) {
            int temp = x1;
            x1 = x2;
            x2 = temp;
        }
 
        // Initialize the minimum time variable
        double res = Double.POSITIVE_INFINITY;
        double lo = x1, hi = x2;
 
        // Ternary Search to find the minimum time
        while (lo <= hi) {
            if (lo == hi) {
                // Update the minimum time if lo and hi are equal
                res = Math.min(res, getTime(lo, x1, y1, x2, y2, v1, v2));
                break;
            }
 
            // Calculate midpoints for ternary search
            double mid1 = lo + (hi - lo) / 3.0;
            double mid2 = hi - (hi - lo) / 3.0;
 
            // Calculate times for midpoints
            double f1 = getTime(mid1, x1, y1, x2, y2, v1, v2);
            double f2 = getTime(mid2, x1, y1, x2, y2, v1, v2);
 
            // Adjust the search range based on comparisons
            if (f1 > f2) {
                res = Math.min(res, f2);
                lo = mid1 + 1;
            } else if (f1 < f2) {
                res = Math.min(res, f1);
                hi = mid2 - 1;
            } else {
                res = Math.min(res, f1);
                lo = mid1 + 1;
                hi = mid2 - 1;
            }
        }
 
        // Output the result with the desired precision
        System.out.printf("%.6f\n", res);
    }
}
 
// This code is contributed by akshitaguprzj3


Python3




import math
 
# Function to calculate the distance between two points
def get_distance(x1, y1, x2, y2, v):
    dx = x1 - x2
    dy = y1 - y2
    return math.sqrt(dx * dx + dy * dy) / v
 
# Function to calculate the total time for the given yCrossingPoint
def get_time(y_crossing_point, x1, y1, x2, y2, v1, v2):
    # Calculate the distance traveled for each segment and return the total time
    return get_distance(x1, y1, y_crossing_point, 0, v1) + get_distance(y_crossing_point, 0, x2, y2, v2)
 
def main():
    x1, y1, x2, y2, v1, v2 = 3, -20, 3, 25, 40, 5
 
    # Ensure x1 <= x2
    if x1 > x2:
        x1, x2 = x2, x1
 
    # Initialize the minimum time variable
    res = float('inf')
    lo, hi = x1, x2
 
    # Ternary Search to find the minimum time
    while lo <= hi:
        if lo == hi:
            # Update the minimum time if lo and hi are equal
            res = min(res, get_time(lo, x1, y1, x2, y2, v1, v2))
            break
 
        # Calculate midpoints for ternary search
        mid1 = lo + (hi - lo) / 3.0
        mid2 = hi - (hi - lo) / 3.0
 
        # Calculate times for midpoints
        f1 = get_time(mid1, x1, y1, x2, y2, v1, v2)
        f2 = get_time(mid2, x1, y1, x2, y2, v1, v2)
 
        # Adjust the search range based on comparisons
        if f1 > f2:
            res = min(res, f2)
            lo = mid1 + 1
        elif f1 < f2:
            res = min(res, f1)
            hi = mid2 - 1
        else:
            res = min(res, f1)
            lo = mid1 + 1
            hi = mid2 - 1
 
    # Output the result with the desired precision
    print("{:.6f}".format(res))
 
if __name__ == "__main__":
    main()


C#




using System;
 
class Program
{
    const double INF = 1e9;
 
    // Function to calculate the distance between two points
    static double GetDistance(double x1, double y1, double x2,
                   double y2, double v)
    {
        double dx = x1 - x2;
        double dy = y1 - y2;
        return Math.Sqrt(dx * dx + dy * dy) / v;
    }
 
    // Function to calculate the total time for the given yCrossingPoint
    static double GetTime(double yCrossingPoint, double x1, double y1,
               double x2, double y2, double v1, double v2)
    {
        // Calculate the distance traveled for each segment and return the total time
        return GetDistance(x1, y1, yCrossingPoint, 0, v1)
               + GetDistance(yCrossingPoint, 0, x2, y2, v2);
    }
 
    static void Main(string[] args)
    {
        int x1 = 3, y1 = -20, x2 = 3, y2 = 25, v1 = 40, v2 = 5;
 
        // Ensure x1 <= x2
        if (x1 > x2)
        {
            int temp = x1;
            x1 = x2;
            x2 = temp;
        }
 
        // Initialize the minimum time variable
        double res = INF;
        double lo = x1, hi = x2;
 
        // Ternary Search to find the minimum time
        while (lo <= hi)
        {
            if (lo == hi)
            {
                // Update the minimum time if lo and hi are equal
                res = Math.Min(res, GetTime(lo, x1, y1, x2, y2, v1, v2));
                break;
            }
 
            // Calculate midpoints for ternary search
            double mid1 = lo + (hi - lo) / 3.0;
            double mid2 = hi - (hi - lo) / 3.0;
 
            // Calculate times for midpoints
            double f1 = GetTime(mid1, x1, y1, x2, y2, v1, v2);
            double f2 = GetTime(mid2, x1, y1, x2, y2, v1, v2);
 
            // Adjust the search range based on comparisons
            if (f1 > f2)
            {
                res = Math.Min(res, f2);
                lo = mid1 + 1;
            }
            else if (f1 < f2)
            {
                res = Math.Min(res, f1);
                hi = mid2 - 1;
            }
            else
            {
                res = Math.Min(res, f1);
                lo = mid1 + 1;
                hi = mid2 - 1;
            }
        }
        // Output the result with the desired precision
        Console.WriteLine(res.ToString("F6"));
    }
}


Javascript




// Function to calculate the distance between two points
function getDistance(x1, y1, x2, y2, v) {
    let dx = x1 - x2;
    let dy = y1 - y2;
    return Math.sqrt(dx * dx + dy * dy) / v;
}
 
// Function to calculate the total time for the given yCrossingPoint
function getTime(yCrossingPoint, x1, y1, x2, y2, v1, v2) {
    // Calculate the distance traveled for each segment and return the total time
    return getDistance(x1, y1, yCrossingPoint, 0, v1)
        + getDistance(yCrossingPoint, 0, x2, y2, v2);
}
 
// Ensure x1 <= x2
let x1 = 3, y1 = -20, x2 = 3, y2 = 25, v1 = 40, v2 = 5;
if (x1 > x2) {
    let temp = x1;
    x1 = x2;
    x2 = temp;
}
 
// Initialize the minimum time variable
const INF = 1e9;
let res = INF;
let lo = x1, hi = x2;
 
// Ternary Search to find the minimum time
while (lo <= hi) {
    if (lo === hi) {
        // Update the minimum time if lo and hi are equal
        res = Math.min(res, getTime(lo, x1, y1, x2, y2, v1, v2));
        break;
    }
 
    // Calculate midpoints for ternary search
    let mid1 = lo + (hi - lo) / 3.0;
    let mid2 = hi - (hi - lo) / 3.0;
 
    // Calculate times for midpoints
    let f1 = getTime(mid1, x1, y1, x2, y2, v1, v2);
    let f2 = getTime(mid2, x1, y1, x2, y2, v1, v2);
 
    // Adjust the search range based on comparisons
    if (f1 > f2) {
        res = Math.min(res, f2);
        lo = mid1 + 1;
    } else if (f1 < f2) {
        res = Math.min(res, f1);
        hi = mid2 - 1;
    } else {
        res = Math.min(res, f1);
        lo = mid1 + 1;
        hi = mid2 - 1;
    }
}
 
// Output the result with the desired precision
console.log(res.toFixed(6));


Output

5.500000







Time Complexity: O(log (max(x1, x2) – min(x1, x2)) ), where x1 is the x-coordinate of starting point and x2 is the x coordinate of ending point.
Auxiliary Space: O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads