Codeforces 431C - k-Tree - [树形DP]

题目链接:https://codeforces.com/problemset/problem/431/C

题意:

定义一个 $k$ 树,即所有节点都有 $k$ 个儿子节点,相应的这 $k$ 条边的权重分别为 $1,2, \cdots, k$。

现在要你求出有多少条路径,从根节点出发,满足路径上至少有一条边的权重不小于 $d$,且路径上的边权总和等于 $n$。

题解:

先记 $f[x]$ 表示,对于一棵 $k$ 树,边权和为 $x$ 的路径有多少条。

此时,若将 $k$ 个 $k$ 树的根作为兄弟,将它们都连在一个新的根节点下,发现构成的依然是一棵 $k$ 树,因此容易想到 $k$ 棵子树往根节点转移的状态转移方法。

然而题目还有一个要求,要路径的最小边权不小于 $d$,那么很简单,我们可以扩展一维,

用 $f[x][1]$ 表示存在一条边的边权不小于 $d$ 的状态,而 $f[x][0]$ 则表示不存在。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
int n,k,d;
ll f[205][2];
int main()
{
    cin>>n>>k>>d;

    memset(f,0,sizeof(f));
    for(int x=1;x<=k;x++)
    {
        if(x<d) f[x][0]=1, f[x][1]=0;
        else f[x][0]=0, f[x][1]=1;
    }
    for(int x=1;x<=n;x++)
    {
        for(int w=1;w<=k;w++)
        {
            if(x-w<=0) break;
            if(w<d)
            {
                f[x][0]+=f[x-w][0], f[x][0]%=mod;
                f[x][1]+=f[x-w][1], f[x][1]%=mod;
            }
            else
            {
                f[x][1]+=f[x-w][0]+f[x-w][1];
                f[x][1]%=mod;
            }
        }
    }

    cout<<f[n][1]<<endl;
}

猜你喜欢

转载自www.cnblogs.com/dilthey/p/10527769.html
今日推荐