计算斯特林数的动态规划方法
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
k<
S(n,k) = 1,如果 k=1 或 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);
}
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];
}
Here's my attempt at determining Stirling numbers using Dynamic Programming.
It is defined as follows:
S(n,k) = S(n-1,k-1) + k S(n-1,k), if 1 < k < n
S(n,k) = 1, if k=1 ou k=n
Seems ok, right? Except when I run my unit test...
partitioningTest ..\src\Test.cpp:44 3025 == s_dynamic(9,3) expected: 3025 but was: 4414
Can anyone see what I'm doing wrong?
Thanks!
BTW, here's the recursive solution:
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);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
发现了错误。
您已经计算了 k=1 的动态斯特林数数组(对于所有 n,S(n,1)=1)。
您应该开始计算 S(n,2) - 即:
Found the bug.
You already computed your dynamic array of Stirlings numbers for k=1 (S(n,1)=1 for all n).
You should start computing S(n,2) - that is:
你的方法很好,除了你似乎犯了一个简单的索引错误。如果您考虑一下索引
i
和j
代表什么,以及内部循环将arr[j]
转换为什么,您就会发现这很容易够了(我撒谎,我花了半个小时才弄清楚那是什么:))。根据我的解码,
i
表示计算期间的值k
,而arr[j]
是由S(i+ j, i-1)
到S(i+1+j, i)
。最上面的 for 循环初始化arr
将其设置为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)
(如果已定义),但不幸的是,Stirling 的数字在k 处未定义=0
。编辑:显然我上次的评论是错误的。如果将 arr 初始化为 {1, 0, 0, ...},则可以将
i
的起始值保留为1
。为此,您可以使用初始值S(0, 0)=1
和S(n, 0)=0, n>0
。Your approach is just fine, except you seem to have made a simple indexing error. If you think about what indexes
i
andj
represent, and what the inner loop transformsarr[j]
to, you'll see it easy enough (I lie, it took me a good half hour to figure out what was what :)).From what I can decode,
i
represents the valuek
during calculations, andarr[j]
is transformed fromS(i+j, i-1)
toS(i+1+j, i)
. The topmost for loop that initializesarr
sets it up asS(1+j, 1)
. According to these loops, the calculations look just fine. Except for one thing: The very firsti
loop assumes thatarr[j]
containsS(0+j, 0)
, and so it is where your problem lies. If you change the starting value ofi
from1
to2
, all should be OK (you may need an if or two for edge cases). The initiali=2
will transformarr[j]
fromS(1+j, 1)
toS(2+j, 2)
, and the rest of the transformations will be just fine.Alternatively, you could have initialized
arr[j]
toS(0+j, 0)
if it were defined, but unfortunately, Stirling's numbers are undefined atk=0
.EDIT: Apparently I was wrong in my last comment. If you initialize arr to {1, 0, 0, ...}, you can leave starting value of
i
as1
. For this, you use the initial valuesS(0, 0)=1
, andS(n, 0)=0, n>0
instead.