【比赛】【树形dp】收集果子

时间:2019-10-23
本文章向大家介绍【比赛】【树形dp】收集果子,主要包括【比赛】【树形dp】收集果子使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

很容易就可以看出这是个树形dp

但是怎么想都是n^3算法,60,卡常70

附上主要dp过程:

(1)直接填表

然后去除了不合法的情况,

在反复wa之后,我......A了???

所以以后循环的范围要好好思考啊

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define ll long long
using namespace std;
int n; ll k;
const int N=1003;
const ll mod=1e9+7;
int sz[N];

ll val[N],tot_val[N],p[N];
ll f[N][N];

inline int read()
{
    int x=0;char c=getchar();
    while(c<'0' || c>'9') c=getchar();
    while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x;
}
struct node
{int v,nx;}e[N<<1];
int tot,head[N];
void add(int u,int v)
{
    e[++tot].v =v,e[tot].nx =head[u],head[u]=tot;
    e[++tot].v =u,e[tot].nx =head[v],head[v]=tot;
}

void dfs(int rt,int fa)
{
    f[rt][val[rt]]=1;
    sz[rt]=1,tot_val[rt]=val[rt];
    
    for(int i=head[rt];i;i=e[i].nx )
    {
        int v=e[i].v ;
        if(v==fa) continue;
        dfs(v,rt);
        sz[rt]+=sz[v],tot_val[rt]+=tot_val[v];
        
        f[v][0]=(f[v][0]+p[sz[v]-1])%mod;
        for(ll j=min(k,tot_val[rt]);~j;j--)
        {
            f[rt][j]=f[rt][j]*f[v][0]%mod;
            for(ll kk=min(j,tot_val[v]) ; kk>=val[v] && kk>0 ;kk--)
                f[rt][j]=( f[rt][j] + f[rt][j-kk]*f[v][kk]%mod )%mod;
        }
    }
}

int main()
{
    n=read(),k=read();
    for(int i=1;i<=n;i++) scanf("%lld",&val[i]);
    for(int i=1;i<n;i++) 
        add(read(),read());
    p[0]=1;
    for(int i=1;i<=n;i++) p[i]=(p[i-1]<<1)%mod;
    
    dfs(1,0);
    printf("%d\n",f[1][k]);
    
    return 0;
}
View Code

原文地址:https://www.cnblogs.com/xwww666666/p/11727113.html