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;
}
View Code

 

posted @ 2013-12-11 22:32  Yours1103  阅读(136)  评论(0编辑  收藏  举报