Динамический программный подход к вычислению числа Стирлинга
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
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);
}
2 ответа
Нашел ошибку. Вы уже вычислили свой динамический массив чисел Стирлинга для k=1 (S(n,1)=1 для всех n). Вы должны начать вычислять 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];
Ваш подход очень хорош, за исключением того, что вы, похоже, допустили простую ошибку индексации. Если вы думаете о том, что индексы i
а также j
представляют, и что внутренний цикл преобразует arr[j]
к, вы увидите это достаточно легко (я лгу, мне понадобилось добрых полчаса, чтобы выяснить, что к чему:)).
Из того, что я могу расшифровать, i
представляет ценность k
во время расчетов и arr[j]
трансформируется из S(i+j, i-1)
в S(i+1+j, i)
, Самый верхний цикл для инициализации 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)
если бы он был определен, но, к сожалению, числа Стерлинга не определены в k=0
,
РЕДАКТИРОВАТЬ: Очевидно, я был неправ в моем последнем комментарии. Если вы инициализируете arr в {1, 0, 0, ...}, вы можете оставить начальное значение i
как 1
, Для этого вы используете начальные значения S(0, 0)=1
, а также S(n, 0)=0, n>0
вместо.