jzoj 5661. 【GDOI2018Day1模拟4.17】药香沁鼻 dp

Description

这里写图片描述

Input

这里写图片描述

Output

这里写图片描述

Sample Input

6 9
1 1 1
1 1 100
8 1 1
1 3 6
2 3 1000
4 1 4

Sample Output

105
【样例解释】
其中一种最优解为:小 C?用 8 点能量摘下第 1,2,4,6 朵花,并放在药材中熬煮,由于第 4 朵花所钦慕的 3 号花不在药材中,所以第 4 朵花渐渐枯萎消失。最后剩下 3 朵花:1,2,6,药材所获得的最大贡献为 1+100+4=105。

Data Constraint
这里写图片描述

分析:其实复杂度主要浪费在合并两个儿子的答案。所以我们可以把一个儿子的答案直接给下一个儿子,就可以了。也就是设f[i][j]表示从根选到i,以及i点左边的子树,容量为j的答案,转移显然。

代码:

#include <iostream>
#include <cstdio>
#include <cmath>

const int maxn=5007;

using namespace std;

int f[maxn][10003];
int n,p,x,cnt;
int val[maxn],w[maxn],ls[maxn],size[maxn],dfn[maxn];

struct node{
    int y,next,w;
}g[maxn*4];

void dfs(int x)
{
    dfn[++cnt]=x;
    size[x]=1;
    for (int i=ls[x];i>0;i=g[i].next)
    {
        dfs(g[i].y);
        size[x]+=size[g[i].y];
    }
}

int main()
{
    freopen("medicine.in","r",stdin);
    freopen("medicine.out","w",stdout);
    scanf("%d%d",&n,&p);
    for (int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&w[i],&x,&val[i]);
        if (i!=1)
        {
            g[i].y=i;
            g[i].next=ls[x];
            ls[x]=i;
        }
    }
    dfs(1); 
    for (int i=n;i>0;i--)
    {
        int k=dfn[i];
        for (int j=0;j<=p;j++) f[i][j]=max(f[i+size[k]][j],0);
        for (int j=w[k];j<=p;j++) f[i][j]=max(f[i][j],f[i+1][j-w[k]]+val[k]);
    }
    int ans=0;
    for (int i=0;i<=p;i++) ans=max(ans,f[1][i]);
    printf("%d",ans);
}

猜你喜欢

转载自blog.csdn.net/liangzihao1/article/details/79974605