找出将N减为零的最小步骤数

时间:2018-11-25 20:26:01

标签: c recursion minimum

过去几天,我在尝试完成以下任务时遇到了一些困难,希望大家能提供帮助:

我给了一个数字N,并且允许我在每一步中对N执行两个操作中的任何一个:

一个-如果我们取2个整数,其中N = x * y,则可以将N的值更改为x和y之间的最大值。

两个-将N的值减小1。

我想找到将N减少到零的最小步骤。 这就是到目前为止,我不确定实现该函数以找到除数(someFindDevisorFunction)的最佳方法是什么,并且如果此“ f ”函数实际上会产生所需的输出,

  int f(int n)
{
  int div,firstWay,secondWay;
  if(n == 0)
    return 0;

  div = SomefindDivisorFunction(n);
  firstWay = 1 + f(n-1);
  if(div != 1)
  {
    secondWay = 1 + f(div);
    if (firstWay < secondWay)
        return firstWay;
    return secondWay;
  }

  return firstWay;
}

例如,如果我输入数字150,则输出为: 75-25-5-4-2-1-0

3 个答案:

答案 0 :(得分:1)

我看到这是一个递归或迭代问题。

OP的方法暗示了递归。


递归解决方案如下:

在每个步骤中,代码都会计算出各种替代方法的步骤:

steps(n) = min(
  steps(factor1_of_n) + 1,
  steps(factor2_of_n) + 1,
  steps(factor3_of_n) + 1,
  ...
  steps(n-1) + 1)

下面的编码解决方案效率低下,但是它确实探索了所有可能性并找到了答案。

int solve_helper(int n, bool print) {
  int best_quot = 0;
  int best_quot_score = INT_MAX;
  int quot;
  for (int p = 2; p <= (quot = n / p); p++) {
    int rem = n % p;
    if (rem == 0 && quot > 1) {
      int score = solve_helper(quot, false) + 1;
      if (score < best_quot_score) {
        best_quot_score = score;
        best_quot = quot;
      }
    }
  }

  int dec_score = n > 0 ? solve_helper(n - 1, false) + 1 : 0;

  if (best_quot_score < dec_score) {
    if (print) {
      printf("/ %d ", best_quot);
      solve_helper(best_quot, true);
    }
    return best_quot_score;
  }
  if (print && n > 0) {
    printf("- %d ", n - 1);
    solve_helper(n - 1, true);
  }
  return dec_score;
}

int main() {
  int n = 75;
  printf("%d ", n);
  solve(n, true);
  printf("\n");
}

输出

75 / 25 / 5 - 4 / 2 - 1 - 0 

迭代

待定

答案 1 :(得分:1)

对于n > 1,您必须测试sqrt(n)n - 1(包括)之间的所有除数,而不仅仅是最大的除数。

这是一种非递归解决方案:

#include <stdio.h>

int main ()
{
    // assume N non-negative                                                    
    int N = 150;

    int next[N + 1];
    int steps[N + 1];

    steps[0] = 0;

    for (int n = 1; n <= N; n++) {
        next[n] = n - 1;
        steps[n] = 1 + steps[n-1];

        for (int i = n - 1; i * i >= n; i--) {
            if (n % i == 0) {
                int tmp = 1 + steps[i];
                if (tmp < steps[n]) {
                    steps[n] = tmp;
                    next[n] = i;
                }
            }
        }
    }

    printf ("%d: %d steps\n", N, steps[N]);

    printf ("%d", N);
    int tmp = N;
    while (tmp != 0) {
        tmp = next[tmp];
        printf (" -> %d", tmp);
    }
    printf ("\n");
}

答案 2 :(得分:0)

如果您开始寻找2的除数,然后向上求,那么找到的最后一对除数将包括最大的除数。另外,您可以从除数= N / 2开始搜索,然后向下搜索,直到找到的第一个除数将是N的最大除数。