【题解】[Codeforces 815C] CF815C Karen and Supermarket【树形DP】

题目链接

题意

\(n\) 个商品呈有根树结构。每个商品有价格 \(c_i\)。若其父亲使用了优惠券,自己可以使用优惠券。给定 \(m\),问 \(m\) 元至多买多少个商品。\(n\leq 5000\)\(c_i,d_i,m\leq 10^9\)

题解

\(f[i,j,0 /1]\) 为考虑 \(i\) 号点的子树、买了 \(j\) 件商品,自己是否使用优惠券时的最小花费。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int getint(){
    int ans=0,f=1;
    char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-')f=-1;
        c=getchar();
    }
    while(c>='0'&&c<='9'){
        ans=ans*10+c-'0';
        c=getchar();
    }
    return ans*f;
}
const int N=5e3+10,mod=998244353,inv2=(mod+1)/2;
struct bian{
    int e,n;
};
bian b[N<<1];
int s[N],tot=0;
void add(int x,int y){
    tot++;
    b[tot].e=y;
    b[tot].n=s[x];
    s[x]=tot;
}

ll f[N][N][2],g[N][2];
int sz[N],c[N],d[N];
void ss(int x){
    f[x][0][0]=0;
    f[x][1][0]=c[x];
    f[x][1][1]=c[x]-d[x];
    sz[x]=1;
    for(int i=s[x];i;i=b[i].n){
        int v=b[i].e;
        ss(v);
        memset(g,0x3f,sizeof(g));
        for(int j=0;j<=sz[x];j++){
            for(int k=0;k<=sz[v];k++){
                g[j+k][0]=min({g[j+k][0],
                    f[x][j][0]+f[v][k][0]});
                g[j+k][1]=min({g[j+k][1],
                    f[x][j][1]+f[v][k][1],
                    f[x][j][1]+f[v][k][0]});
            }
        }
        sz[x]+=sz[v];
        memcpy(f[x],g,sizeof(g));
    }
    // cerr<<">>>>>>> "<<x<<endl;
    // for(int i=0;i<=sz[x];i++)cerr<<"|| "<<i<<" "<<f[x][i][0]<<" "<<f[x][i][1]<<endl;
}

int main(){
    int n=getint(),b=getint();
    for(int i=1;i<=n;i++){
        c[i]=getint();
        d[i]=getint();
        if(i>=2)add(getint(),i);
    }
    memset(f,0x3f,sizeof(f));
    ss(1);
    int ans=0;
    for(int i=1;i<=n;i++)if(f[1][i][0]<=b||f[1][i][1]<=b)ans=i;
    cout<<ans;
}

posted @ 2020-12-31 09:36  破壁人五号  阅读(143)  评论(0编辑  收藏  举报