Мой подход к таким задачам (один из них я получил от projecteuler.net) состоит в том, чтобы вычислить первые несколько членов последовательности, а затем искать в oeis последовательность с теми же терминами. Это может привести к решениям на порядок быстрее. В вашем случае последовательность, вероятно, равна: http://oeis.org/A178031, но, к сожалению, она не имеет простой в использовании формулы.
:
Поскольку ограничение для n относительно мало, вы можете выполнить dp на минимальном количестве шагов, необходимых для перехода к паре (a, b) из (1,1). Вы берете двумерный массив, в котором хранится ответ для данной пары, а затем делаете рекурсию с памяткой:
int mem[5001][5001];
int solve(int a, int b) {
if (a == 0) {
return mem[a][b] = b + 1;
}
if (mem[a][b] != -1) {
return mem[a][b];
}
if (a == 1 && b == 1) {
return mem[a][b] = 0;
}
int res;
if (a > b) {
swap(a,b);
}
if (mem[a][b%a] == -1) { // not yet calculated
res = solve(a, b%a);
} else { // already calculated
res = mem[a][b%a];
}
res += b/a;
return mem[a][b] = res;
}
int main() {
memset(mem, -1, sizeof(mem));
int n;
cin >> n;
int best = -1;
for (int i = 1; i <= n; ++i) {
int temp = solve(n, i);
if (best == -1 || temp < best) {
best = temp;
}
}
cout << best << endl;
}
На самом деле в этом случае нет большой разницы между dp и BFS, но это общий подход к таким проблемам. Надеюсь, это поможет.
EDIT: вернуть достаточно большое значение в dp, если a равно нулю