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.500000Input: 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:
#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;
}
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
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()
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"));
}
}
// 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)