计算斯特林数的动态规划方法

时间:2011-02-27 11:50:24

标签: c++ c algorithm dynamic-programming non-recursive

int s_dynamic(int n,int k) {
    int maxj = n-k;

    int *arr = new int[maxj+1];

    for (int i = 0; i <= maxj; ++i)
        arr[i] = 1;

    for (int i = 1; i <= k; ++i)
        for(int j = 1; j <= maxj; ++j)
            arr[j] += i*arr[j-1];

    return arr[maxj];
}

这是我尝试使用动态编程确定斯特林数字。

定义如下:

  

S(n,k)= S(n-1,k-1)+ k S(n-1,k),如果1 <1。 k&lt; n

     

S(n,k)= 1,如果k = 1 ou k = n

好吧,好吧?除非我进行单元测试...

partitioningTest ..\src\Test.cpp:44 3025 == s_dynamic(9,3) expected:    3025    but was:    4414    

谁能看到我做错了什么?

谢谢!

顺便说一下,这是递归解决方案:

int s_recursive(int n,int k) {
    if (k == 1 || k == n)
        return 1;

    return s_recursive(n-1,k-1) + k*s_recursive(n-1,k);
}

2 个答案:

答案 0 :(得分:4)

发现错误。 您已经计算了k = 1的斯特林数的动态数组(对于所有n,S(n,1)= 1)。 你应该开始计算S(n,2) - 即:

for (int i = 2; i <= k; ++i) //i=2, not 1
  for(int j = 1; j <= maxj; ++j)
    arr[j] += i*arr[j-1];

答案 1 :(得分:3)

你的方法很好,除了你似乎做了一个简单的索引错误。如果您考虑ij所代表的索引以及内循环将arr[j]转换为什么,您会看到它很容易(我撒谎,我花了半个小时弄清楚是什么:))。

根据我可以解码的内容,i代表计算期间的值karr[j]S(i+j, i-1)转换为S(i+1+j, i)。初始化arr的最顶层for循环将其设置为S(1+j, 1)。根据这些循环,计算看起来很好。除了一件事:第一个i循环假设arr[j]包含S(0+j, 0),因此它就是您的问题所在。如果您将i的起始值从1更改为2,则所有内容都应该正常(您可能需要if或者两个边缘情况)。最初的i=2会将arr[j]S(1+j, 1)转换为S(2+j, 2),其他转换将会很好。

或者,您可以将arr[j]初始化为S(0+j, 0)(如果已定义),但不幸的是,斯特林的数字在k=0未定义。

编辑:显然我上次评论错了。如果将arr初始化为{1,0,0,...},则可以将i的起始值保留为1。为此,您可以使用初始值S(0, 0)=1S(n, 0)=0, n>0