USACO 2.3.2 奶牛家谱 Cow Pedigrees

题解

这道题你想模拟建树的方法来做是肯定行不通的,有高度有节点数,两种限制,有点背包的意思。
F [ i , j ] 代表有 j 个节点 i 层的树 的表示数量
显然每棵树都可分为根节点和左右两子树,我们只需让左右子树的最高高度为 i-1 以及其节点和为 j-1 就好了。
这样的情况只有三种:
1. 左右子树高度均为 i - 1
2. 左子树高度为 i - 1 , 右子树高度小于 i - 1
3. 右子树高度为 i - 1 , 左子树高度小于 i - 1

那么状态转移方程可写作
F [ i , j ] += F [ i-1 , k ] * F [ i-1 , j-1-k ]
F [ i , j ] += sm[ i-2 k ] * F [ i-1 , j-1-k ]
F [ i , j ] += F [ i-1 , k ] * sm[ i-2 , j-1-k]

// sm[i,j] 代表高度小于等于i 节点数为 j 的 方案数 综合。


Code

// head files excluded
using namespace std;
int n,m,k;

int f[102][202];
int sm[102][202];
int main(void){

    cin>>n>>m;
    f[1][1] = 1;
    for(int i=2;i<=m;i++){

        for(int j=3;j<=n;j+=2){

            for(int k=1;k<=j-1;k+=2){

                f[i][j]+=f[i-1][k]*f[i-1][j-1-k];
                f[i][j]+= sm[i-2][k]*f[i-1][j-1-k];     
                f[i][j]+= f[i-1][k]*sm[i-2][j-1-k];     

                f[i][j]%=9901;
            }   
        }

        for(int k=0;k<=n;k++){
            sm[i-1][k]=sm[i-2][k]+f[i-1][k];
            sm[i-1][k]%=9901;
        }
    }

    cout<
    return 0;
}

你可能感兴趣的:(USACO,树及衍生物,动态规划)