The problem is as follows:
Problem:
"Your car starts at position 0 and speed +1 on an infinite number line. Your car can go into negative positions. Your car drives automatically according to a sequence of instructions 'A' (accelerate) and 'R' (reverse):
When you get an instruction 'A', your car does the following:
position += speed
speed *= 2
When you get an instruction 'R', your car does the following:
If your speed is positive then speed = -1
otherwise speed = 1
Your position stays the same.
For example, after commands "AAR", your car goes to positions 0 --> 1 --> 3 --> 3, and your speed goes to 1 --> 2 --> 4 --> -1.
Given a target position target, return the length of the shortest sequence of instructions to get there."
Source: https://leetcode.com/problems/race-car/description/
Proposed DP solution:
Let DP[i] be the number of instructions needed to travel a distance "i" in the right-hand direction.
Then DP[0] = 0
For our update rule, there are 3 cases.
First reach some j < i without reversing, then reverse and travel some distance to k < j. Finally, reverse again and use the previously solved DP[i-k]
First, reach some j > i without reversing, then reverse and use the previously solved DP[j-i]
We can reach i without reversing
According to the above update rules, we can solve from DP[0] to DP[i] to obtain our solution.
Issue:
This seems to be the widely accepted DP solution to this problem, but I have yet to find a satisfying proof, or even any proof at all, that this algorithm is correct.
For example, how could one prove that the optimal way to traverse a distance "i" isn't to immediately reverse and go to some a < 0, then reverse and travel to some j > i, and finally reverse again and use DP[j-i]?
Or how could one prove that the optimal way to traverse a distance "i" isn't to overshoot to a distance j > 2i, and then reverse and travel a distance 2i - j > i, which is a subproblem that would not yet have been solved?
Many "proofs" I come across make vague statements such as "it should be clear that you don't want to go overshoot to j > 2i" and so on which is less than rigorous.
My current thoughts:
At the moment, I can at least put forth what I think is a valid proof to prove that we would never want to first reverse to some a < 0, then reverse to some j > i, and then make our way back to DP[j-i].
My proof for this is that in this case, we would reverse a total of 3 times. Rather than do this, we could simply make our way to j + a without reversing, then reverse once and go to j, then reverse twice (reverse once to set speed to 0, and then reverse again to point back towards i) and go to i. I believe this should result in the same amount of steps in the end.
However, I still have trouble proving why we would never overshoot to some j > 2i and then make our way back to i?
If anyone could provide a proof for this solution, that would be much appreciated, thank you!
Well, how would we get there? Call the vector (the last jump) that led there
v.If we issued
vfrom a position afteri, that would be redundant as we can use the recurrence we defined forj > iwithout thevjump.And if we issued
vfrom beforeito get to a distance greater than2*i, it's simple: we can't. Aside fromi = 2^p - 1, which has a trivial solution, we cannot achieve a magnitude greater thani / 2, necessary to leap farther thani, beforei.(Note that the interpretation of
j > iis taken from the recurrence explanation at https://leetcode.com/problems/race-car/solutions/124326/summary-of-the-bfs-and-dp-solutions-with-intuitive-explanation)We can prove that going below position 0 is unnecessary by observing that any sequence
sstarting at 0 and ending at some lowest pointlbelow zero will have a subsequent sequences'that starts by going higher and takes it all the way toi, never going as low asl. We can switch the order so thats'is executed first and thens. There are two cases, depending on the directions'ends in.One case is when
s'ends going left (note that the drawing makes the rightmost point ofsands'the same as their visual right end but the rightmost point in their sequence could be farther):When
s'ends going right, defineVas the first section ofsuntil it first reverses to go below zero, and defineUas the first vector ofs'(we defined it already as going right).If
V's magnitude is smaller than or equal toUs, mergeVwiths'and applyVagain at the end:If
V's magnitude is greater thanUs, applyVinstead ofUand applyUat the end: