One problem is that what is the "fastest" depends on x
. For example with x=0
initially then x+x
is not going to grow much, and also with x=1
the fastest is x+2
, not x+x
.
I'd use a direct full-search approach:
int min_steps(int x, int y) {
std::set<int> active, seen;
active.insert(x); seen.insert(x);
int steps = 0;
while (active.size() && active.find(y) == active.end()) {
// `active` is the set of all populations that we can
// reach in `steps` number of steps or less not greater
// than the target value `y`.
// The next set is computed by starting from every value
// and applying every possible growth function.
// `seen` is the set of all values we saw before to avoid
// adding a value that has been checked before.
steps++;
std::set<int> new_active;
for (std::set<int>::iterator i=active.begin(),e=active.end();
i!=e; ++i) {
for (int f=0; f<3; f++) {
int z;
switch(f) {
case 0: z = *i + 1; break;
case 1: z = *i + 2; break;
case 2: z = *i + *i; break;
}
if (z <= y && seen.find(z) == seen.end()) {
new_active.insert(z);
seen.insert(z);
}
}
}
active = new_active;
}
return active.size() ? steps : -1;
}
Given the look of the graph of the number of steps to get from 1 to x with x <= 1000 my wild guess is however that there's a closed form for the solution: looks not obvious but not totally random...