csuoj 1351: Tree Counting
这是一个动态规划的题;
当初想到要用dp,但是一直想不到状态转移的方程;
题解上的原话:
动态规划,设 g[i]表示总结点数为 i 的方案种数,另设 f[i][j]表示各个孩子的总结点数为
i,孩子的个数为 j 的方案数,那么有 g[i+1]=f[i][1]+f[i][2]+...+f[i][k],相当于添加一个根节
点之后变成完整的树,同时要把有 1 个孩子,2个孩子, ……,k 个孩子的情况都考虑进去。
对于 f[i][j]的求解可以用类似背包的方法去做,在求解的时候也会用到 g[1], g[2], ..., g[i]
的值,根据前面的那个 g[i+1]的表达式来看,这些 g[]已经在前面算出来了。
代码:
#include<cstdio> #include<cstring> #include<algorithm> #define maxn 205 #define mod 1000000007 using namespace std; long long dp[maxn],f[maxn][22]; int main() { int t,n,k; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&k); memset(dp,0,sizeof dp); memset(f,0,sizeof f); f[0][0]=1; dp[1]=1; for(int i=1;i<n;i++) { for(int j=1;j<=k;j++) for(int v=1;i-v>=j-1;v++) f[i][j]=(f[i][j]+dp[v]*f[i-v][j-1])%mod; for(int j=1;j<=k;j++) dp[i+1]=(dp[i+1]+f[i][j])%mod; } printf("%lld\n",dp[n]); } return 0; }