Динамический программный подход к вычислению числа Стирлинга

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 вместо.

Другие вопросы по тегам