C++树形DP—————二叉苹果树

版权声明:蒟蒻原创博客,大佬转载也需附上链接: https://blog.csdn.net/weixin_43810158/article/details/88845246

题目描述:

有一棵苹果树,如果树枝有分叉,一定是分 2 叉(就是说没有只有 1 个儿子的结点)。这棵树共有 N 个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是 1。 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有 4 个树枝的树:

现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。 给定需要保留的树枝数量,求出最多能留住多少苹果。

输入:

第1行: 2个空格分开的整数,N 和 Q(1≤Q≤N,1<N≤100),N表示树的结点数,Q表示要保留的树枝数量。 接下来 N-1 行描述树枝的信息。 每行3 个整数,前两个是它连接的结点的编号。第3 个数是这根树枝上苹果的数量。 每根树枝上的苹果不超过30000 个。

输出:

第1行:一个整数,表示最多能留住的苹果的数量。

样例输入:

5 2 
1 3 1 
1 4 10 
2 3 20 
3 5 20 

样例输出:

21

思路分析:

这一题是较为简单的树形DP题。

分析题意可得,我们可以看出这是一个分组背包问题

只不过是在树上罢了,而遍历只需要在它与儿子之间即可。

如果对树形DP不了解,可以戳一下

代码实现:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
using namespace std;
struct node{
    int v,w;
};
vector<node>G[105];
int n,m,f[105][105];
void dfs(int x,int fa)
{
    for(int i=0;i<G[x].size();i++)
    {
        int v1=G[x][i].v;
        int w1=G[x][i].w;
        if(w1==fa)
            continue;
        dfs(w1,x);
        for(int j=m;j>0;j--)
            for(int k=0;k<j;k++)
                f[x][j]=max(f[x][j],f[x][k]+v1+f[w1][j-k-1]);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    int a,b,c;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        node t;
        t.w=b;
        t.v=c;
        G[a].push_back(t);
        t.w=a;
        G[b].push_back(t);
    }
    dfs(1,-1);
    printf("%d",f[1][m]);
}

猜你喜欢

转载自blog.csdn.net/weixin_43810158/article/details/88845246