优化递归函数

时间:2016-01-09 16:29:47

标签: c++ function recursion optimization

我正在创建一个程序,它只返回使用1,2,6和13来获得数字(n)所需的最小数量。它适用于n的小值,但是一旦得到n对于像200这样的值,程序需要花费太多时间来计算结果。

因此,我有两个问题:

1。有没有办法让递归更快?

2. 我应该避免使用递归并改为使用循环吗?

以下是注释代码:

#include <iostream>
#define MAX 500000

using namespace std;

void cal(int inp, int &mini, int counter = 0);

int main (void)
{
    //Gets input
    int n;
    cin >> n;

    //Defines mini as the MAX result we can get
    int mini = MAX;

    //Calls the function
    cal(n, mini);

    //Prints the best result
    cout << mini << endl;

    return 0;
}

void cal(int inp, int &mini, int counter)
{
    //Breaks recursion if it finds an answer
    if(!inp)
    {
        if(counter<mini) mini = counter;
        return;
    }

    //Breaks recursion if the input is negative
    //or the counter is more than the best result
    else if((inp<0) || (counter>mini)) return;

    //Counts amount of recursions
    counter++;

    //Tries every combination
    cal(inp-13, mini, counter);
    cal(inp-6, mini, counter);
    cal(inp-2, mini, counter);
    cal(inp-1, mini, counter);

    return;
}

谢谢

3 个答案:

答案 0 :(得分:4)

问题在于你的暴力。让我提出更好的建议:

预备:如果你有两个1,最好使用2个。如果你有3个2,最好使用6个。如果你有13个6s,最好使用6个12个。

所以任何可以接受的总和总是看起来像n = 13m+k,其中k被写为1,2和6的总和。通过预备,我们知道最佳总和{{1永远不会超过k。 (相反的情况并不成立。当然,没有任何低于78的数字最好在没有13s的情况下写出来。)所以粗暴强迫这些就足够了。然后,您可以使用查找表。

这仍然可以进一步优化,但它不应该在200下降。

假设您找到了前77个条目(也可以进行优化),您可以这样做(仍未优化; - ):

1+2*2+12*6 = 77

我甚至可以更快地为等价类modulo 13编译数组,因为对于任何给定的等价类,任何超过78的数字都将具有相同的int num_13 = ((n-78) / 13) + 1; int sum_length = MAX; for (i = num_13; i*13 < n; i++) { int tmp = entries_77[n-i*13]+i; if (tmp < sum_length) { num_13 = i; sum_length = tmp; } }

答案 1 :(得分:4)

您可以使用DP(动态编程)方法来解决您的问题。众所周知Coins Problem

答案 2 :(得分:1)

您的递归需要记忆以避免重复计算。并且不需要递归的第二个和第三个参数。我已经更新并对您的代码进行了解释。如果你有任何困惑,请告诉我。

llo

这也适用于更大的数字。复杂性是4 * n。