Codeforces 431C k-Tree(记忆化搜索)

题目链接

题目大意

  给无限深度一颗k叉树,每个最小子树的边的权值都是1~k,问有多少从根结点出发,路径和为n且最少一条边为d的路径。

解题思路

  首先看到要取模就知道直接枚举出所有的情况肯定是不可取的。考虑一下,如果有一条路径可以到达n,那之前肯定有路径可以到达n-1、n-2...n-k,然后在前一个状态的基础上再往前推,就能推到0~k的状态,所以我们只要能得到0~k的状态,也能往后推出到达n的状态。如果不考虑d的话,这个还是很好写的,很显然用一个递归就能完成这个操作,而且用数组直接就可以存储到达某个状态的路径数量。
  考虑至少有一条路径为d的情况。我们考虑对于当前的状态q,他也是有q-1、q-2...q-k等若干个子状态转移过来的,但是这里的子状态有两种情况,一种是至少有一条边大于d,一种是没有大于d的边,所以对于同一个q来说可能存在两种状态,而在优化过程中,对这两种状态都要就行存储并且区分。

代码

const int maxn = 1e2+10;
int n, k, d; ll ans, rec[maxn][3];
int dfs(int now, bool flag) {
    if (!now) return rec[now][flag] = flag; 
    if (rec[now][flag]!=-1) return rec[now][flag];
    ll tmp = 0;
    for (int i = 1; i<=k; ++i)
        if (now-i>=0) tmp = (tmp+dfs(now-i, flag||(i>=d)))%MOD;
        //当前状态的所有可能是子状态之和,如果某个子状态没有大于d的边,那么它的值就是0
    return rec[now][flag] = tmp;
}
int main() {
    cin >> n >> k >> d; NIL(rec);
    cout << dfs(n,0) << endl;
    return 0;
}
posted @ 2020-05-18 23:34  shuitiangong  阅读(168)  评论(0编辑  收藏  举报