Codeforces 431C k-Tree(记忆化搜索)
Posted shuitiangong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
}
以上是关于Codeforces 431C k-Tree(记忆化搜索)的主要内容,如果未能解决你的问题,请参考以下文章
「专题训练」k-Tree(CodeForces Round #247 Div.2 C)