Bytelandian金币解释?

时间:2015-04-16 16:46:32

标签: c recursion dynamic-programming memoization

我正在尝试这里提到的Bytelandian金币问题 - http://www.codechef.com/problems/COINS/这是其中一个解决方案 -

#include <stdio.h>
long int a[30][19];  //1
long int recur(long int n, int i, int j);
int main()
{
    long int n;
    int i, j;
    while (scanf("%lld", &n) != EOF)
    {
        for (i = 0; i < 30;i++)
        for (j = 0; j < 19; j++)
            a[i][j] = 0;
        long int v = recur(n, 0, 0);
        printf("%lld\n", v);
    }
    return 0;
}
long int recur(long int n, int i, int j)
{
    if (n <12 )  //2
        return n;
    else if (!a[i][j])
    {
        long int t = recur(n / 2, i + 1, j) + recur(n / 3, i, j + 1) + recur(n / 4, i + 2, j);
        a[i][j] = t;
    }

    return a[i][j];
}

在这段代码中,我无法理解两点 - 1 - 数组a [30] [19]的大小,它基于输入数字的最大值可被2或3整除的最大次数,它们使用一些对数基数2或3公式来查找.Can有人请解释这个公式,这是一些数学属性,如果是,我在哪里可以找到更多的信息。 2 - 停止递归n&lt; 12条件被使用,因为12以下的所有数字将具有与自身相等的值作为最大值。我无法理解它是如何被发现的。我的意思是如果我替换了它,他们如何发现12是限制值原来的复发功能我得到了错误的答案 -

long int recur(long int n, int i, int j)
{
    if ((n == 0) || (n == 1) || (n == 2) )
        return n;
    else if (!a[i][j])
    {
        long int t = recur(n / 2, i + 1, j) + recur(n / 3, i, j + 1) + recur(n / 4, i + 2, j);
        a[i][j] = n> t ? n : t;
    }

    return a[i][j];
}

如果有人请解释上述2点,我将不胜感激

1 个答案:

答案 0 :(得分:0)

  1. i 的上限来自条件 2 i ≤10 9 (次数10 9 可以除以2直到达到1等于1的次数可以乘以2直到达到10 9 ;求解 i 得出i≤log 2 (10 9 ≅29.9。
    另一种看待它的方法是将10 9 表示为二进制数111011100110101100101000000000 2 ;这个数字有30个数字,每个整数除以2得到一个数字减去(删除最右边的数字),所以在29个分区之后我们到达1.
    正如JohnH在上面的评论中正确指出的那样, i 的最大值仍然低于29,因为递归不会下降到 n = 1 ,而是停在 n&lt; 12
    大约相同的是 j 的上限和除以3. 10 9 作为三元数是2120200200021010001 3 ;这个数字有19位数字;在17个整数除以3之后,我们到达21 3 = 7,递归停止。

  2. 要知道12以下的所有数字都等于其最高交换金额,我们可以简单地尝试一下:

     n  n/2  n/3  n/4  sum of the 3 exchanged coins
     1   0    0    0    0
     2   1    0    0    1
     3   1    1    0    2
     4   2    1    1    4
     5   2    1    1    4
     6   3    2    1    6
     7   3    2    1    6
     8   4    2    2    8
     9   4    3    2    9
    10   5    3    2   10
    11   5    3    2   10
    12   6    4    3   13
    

    我们看到12是交换时产生高于其自身值的最低数字。

      

    如果我用这个替换原来的复现功能我就错了   回答 -

    n = 509607936 上,您会收到“错误答案”,因为long int t等溢出到负值。奇怪的是,对于原始recur函数,此错误由另一个错误补偿,即BLUEPIXY指出的错误转换规范%lld。通过使用类型a定义recurtvunsigned long int并使用适当的转换规范%lu,可以更正该计划。< / p>