Home > database >  How can I use the Approximate algorithm in this problem?
How can I use the Approximate algorithm in this problem?

Time:04-03

Imagine that a needle in the speedometer, which shows the speed, has fallen off.

It was reattached, but not at the right angle. So, although the speedometer showed the value of the current speed v, its actual value was v k, where k is an unknown constant (probably also negative). So we started keeping honest records of the trips we made to find out the value of the mysterious constant k.

Input:

The first line of the input contains two integers: n (1 ≤ n ≤ 1000), which represents the number of parts of a single run, and t (1 ≤ t ≤ 10^6), which represents the total run time.

This is followed by n lines, where each describes one part of the trip that we recorded. Each line contains two integers: s (1 ≤ s ≤ 1000) and v (|v| ≤ 1000), the distance and speed indicated by the speedometer with the needle stuck on during that part of the journey. Keep in mind that even though the speedometer needle on the glove box may have negative readings, its actual speed was always greater than 0 during every part of the trip. The time is given in hours, the distance in kilometres and the speed in kilometres per hour.

Output:

The problem is to find K. The mysterious constant k given in kilometers per hour.

Example of Input:

3 5
4 -1
4 0
10 3

Output:

3.000000000

Input:

4 10
5 3
2 2
3 6
3 1

Output:

-0.508653377

Well, I was told that this problem can be solved with Approximate algorithm.

Can someone write a pseudocode solution or explain how exactly I can solve this problem with this algorithm?

CodePudding user response:

All of this was mentioned in comments, but it's not clear...

If you guess a value for k, then you can determine how long the whole trip would have taken if that guess was correct:

Total time T = distance1/(speed1 k) distance2/(speed2 k)...

If this total time is more than the actual total time given in the problem, then your guess is too small (you went faster than you guessed). If the guessed total time is less than the actual total time, then your guess is too big (you went slower than you guessed).

With the ability to make and test these guesses, you can play the higher/lower game to narrow down the range of possible k values until you get as close to the real value as you want.

You can't necessarily get to the exact value, which is why this could be called an approximate algorithm. But the numbers we work with also have limited precision, so they probably can't even represent the exact value. You can easily get one of the closest representable values, which is just as good as an "exact" calculation.

The algorithm for playing the higher/lower game is called "binary search". It's a little tricky with doubles, so I'll write it out. Given a function isTooHigh that tests a guess for k, you can do it like this:

double findk()
{
    double lo = -minOfAll(speeds);
    double hi = max(1.0, lo);
    while(!isTooHigh(hi)) {
        hi *= 2.0;
    }
    while(lo < hi) {
        double test = lo   (hi-lo)*0.5;
        if (isTooHigh(test)) {
            if (test >= hi) {
               // we've reached the limit of precision
               break;
            }
            hi = test;
        } else {
            if (test <= lo) {
               // we've reached the limit of precision
               break;
            }
            lo = test;
        }
    }
    return lo;
}

Note that, because of the way double-precision numbers are represented, this loop could iterate up to a 2000 times if k is 0 or very close to it. If you don't want that, then you can change the (lo < hi) test to (lo < hi - REALLY_SMALL). You will have to put up with a less accurate answer, but you can limit the maximum number of iterations.

There are also other approximate algorithms you could use that require fewer iterations, like Newton's method

  • Related