Как мне добавить это условие в это и сделать его оптимальным?

Ссылка на вопрос: http://codeforces.com/problemset/problem/431/C

Совсем недавно творческая ученица Леша провела лекцию по деревьям. После
лекция леша была вдохновлена ​​и придумала собственное дерево
который он назвал к-деревом.

K-дерево — это бесконечное корневое дерево, где:

  • каждая вершина имеет ровно k детей;
  • каждый край имеет некоторый вес;
  • если мы посмотрим на ребра, идущие от некоторой вершины к ее дочерним элементам (точно
    k ребер), то их веса будут равны 1, 2, 3, …, k.

На рисунке ниже показана часть 3-х деревьев.

введите описание изображения здесь

Как только Дима, хороший друг Леши, узнал о дереве, он
Сразу задумался: «Сколько дорожек общего веса n (сумма
все веса ребер в пути), начиная с
корень k-дерева, а также содержащий по крайней мере один край веса в
хотя бы д? ». Помогите Диме найти ответ на свой вопрос. По количеству
пути могут быть довольно большими, выведите его по модулю 1000000007 (10 ^ 9 + 7). (Открыто
ссылка на вопрос выше для картины упомянутого дерева)

вход
Одна строка содержит три целых числа через пробел: n, k и
d (1 ≤ n, k ≤ 100; 1 ≤ d ≤ k).

Выход
Выведите одно целое число — ответ на задачу по модулю
1000000007 (10 ^ 9 + 7).

Итак, я попытался разработать рекурсивное решение для того же. Тем не менее, я не могу добавить ограничение, чтобы убедиться, что край веса по крайней мере d должен присутствовать. Как я могу это сделать? Вот моя рекурсивная функция:

void calc(int present, int total,int k) // Here, present is initialised to 0.
// total is equal to n that is reqd.
// k is the value in the question
{
if (total == present)
{
ans++;
ans = ans%val;
return;
}
else
{
for ( int i = 1; i <= k; i++ )
{
if (present+i <= total)
return calc(present+i,total,k);
}
}
}

4

Решение

Просто добавьте следующие аргументы к вашей функции — d и достигли ли вы ограничения, что один из этих ребер по крайней мере d,

void calc(int present, int total,int k, int d, bool atleastd)
{

Измените ограничение на приращение, только если atleastd,

    if (total == present && atleastd)
{
ans++;
ans = ans%val;
return;
}
else
{
for ( int i = 1; i <= k; i++ )
{
if (present+i <= total)

Когда вы рекурсивно вызываете свою функцию, передаете ли atleastd уже был достигнут раньше, или же если вы только что выполнили это ограничение (i >= d).

                calc(present+i,total,k,d,atleastd || i >= d);

Кроме того, я удалил return в предыдущей строке. В противном случае код будет проверять только 1 возможный путь — путь, где все веса == 1.

        }
}
}

Я предполагаю что ans а также val являются глобальными, ans является ответом на проблему, инициализированный в 0, и val по модулю = 1000000007.


Наконец, хотя это решение может решить небольшие тестовые случаи, где n <= 15, это будет слишком медленно для n = 100.

Чтобы решить для n = 100, я предлагаю узнать о мемоизации а также динамическое программирование. Я оставлю это как упражнение для вас.

2

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector