如何在此中添加此条件并使其最佳化?

时间:2015-10-03 08:21:36

标签: c++ algorithm tree

问题链接是:http://codeforces.com/problemset/problem/431/C

  

最近,一位有创造力的学生Lesha在树上做了一个讲座。后   讲座Lesha受到启发并想出了他自己的树   他称之为k树。

     

k-tree是一个无限的有根树,其中:

     
      
  • 每个顶点都有k个孩子;
  •   
  • 每条边都有一些重量;
  •   
  • 如果我们看一下从某个顶点到其子节点的边缘(确切地说   k个边缘),然后它们的权重将等于1,2,3,...,k。
  •   
     

下图显示了3棵树的一部分。

     

enter image description here

     

一旦Lesha的好朋友Dima发现了这棵树,他就会   马上想知道:“总重量的路径数n(总和)   从那里开始,路径中边缘的所有权重都在那里   k树的根,并且还包含至少一个重量边缘   至少d?“。帮助Dima找到他的问题的答案。作为数量   方式可以相当大,打印模数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);
        }
    }
}

1 个答案:

答案 0 :(得分:2)

只需在函数中添加以下参数 - 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的路径。

        }
    }
}

我假设ansval是全局变量,ans是问题的答案,初始化为0,val是模数= 1000000007。

最后,虽然这个解决方案可以解决n <= 15的小测试用例,但是对于n = 100来说它会太慢。

要解决n = 100,我建议您了解memoizationdynamic programming。我将把这作为练习留给你。