动态规划 树型DP

codves5565 二叉苹果树

时间限制: 1 s

空间限制: 128000 KB

题目描述 Description

有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。
       给定需要保留的树枝数量,求出最多能留住多少苹果。

输入描述 Input Description

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

输出描述 Output Description

剩余苹果的最大数量。

样例输入 Sample Input

5 2

1 3 1

1 4 10

2 3 20

3 5 20

样例输出 Sample Output

21

数据范围及提示 Data Size & Hint

对于20%数据 n<=20;

对于100%数据1<N<=100,1<=Q<= N.

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct node
{
    int l,r,c;
}map[2001];
int f[1005][1005];
int n,q,maxx=0;
void dfs(int i,int j)
{
    int k;
    if(j==0) f[i][j]=0;
    else if(map[i].r==0&&map[i].l==0) f[i][j]=map[i].c;
    else
    {
        f[i][j]=0;
        for(k=0;k<j;k++)
        {
            if(f[map[i].l][k]==0) dfs(map[i].l,k);
            if(f[map[i].r][j-k-1]==0) dfs(map[i].r,j-k-1);
            f[i][j]=max(f[i][j],f[map[i].l][k]+f[map[i].r][j-k-1]+map[i].c);
            //    maxx=max(maxx,f[i][j]);
            //printf("%d ",maxx);
        }
    }
}

int main()
{

    scanf("%d %d",&n,&q);
    int v,u,c;
    for(int i=1;i<n;i++)
    {
        int p=0;
        scanf("%d %d %d",&v,&u,&c);
        for(int j=1;j<=n;j++)
            if(map[j].l==u||map[j].r==u) p=1;
            if(p==0)
            {
                if(map[v].l==0) map[v].l=u;
                else if(map[v].r==0) map[v].r=u;
                map[u].c=c;
            }
            else
            {
                if(map[u].l==0) map[u].l=v;
                else if(map[u].r==0) map[u].r=v;
                map[v].c=c;
            }
    }
    //for(int i=1;i<=n;i++) printf("%d %d %d\n",map[i].l,map[i].r,map[i].c);
        dfs(1,q+1);        

    //for(int i=1;i<=n;i++) printf("%d ",map[i]);
    printf("%d",f[1][q+1]);
}

初始化:f[i][0]=0,f[i][1]=map[i];

转移方程:f[i][j]=max(f[i][j],f[map[i].l][k]+f[map[i].r][j-k-1]+map[i].c);

谢谢姚老教导;

接下来膜ccz大爷  附代码   很强势;

#include<bits/stdc++.h>
struct edge{
    int to,v;
};
int n,q;
std::vector<edge>e[107];
int f[107][107],sz[107],v[107];
void maxs(int&a,int b){if(a<b)a=b;}
void f1(int w,int pa){
    sz[w]=1;
    f[w][1]=v[w];
    for(int i=0;i<e[w].size();++i){
        int u=e[w][i].to;
        if(u==pa)continue;
        v[u]=e[w][i].v;
        f1(u,w);
        for(int k=sz[w];k>=1;--k)
        for(int j=1;j<=sz[u];++j){
            maxs(f[w][k+j],f[w][k]+f[u][j]);
        }
        sz[w]+=sz[u];
    }
}
int main(){
    scanf("%d%d",&n,&q);
    for(int i=1,a,b,c;i<n;++i){
        scanf("%d%d%d",&a,&b,&c);
        e[a].push_back((edge){b,c});
        e[b].push_back((edge){a,c});
    }
    f1(1,0);
    printf("%d\n",f[1][q+1]);
    return 0;
}

------------------------

codves1380 没有上司的舞会

时间限制: 1 s

空间限制: 128000 KB

题目描述 Description

Ural大学有N个职员,编号为1~N。他们有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上司。每个职员有一个快乐指数。现在有个周年庆宴会,要求与会职员的快乐指数最大。但是,没有职员愿和直接上司一起与会。

输入描述 Input Description

第一行一个整数N。(1<=N<=6000)
接下来N行,第i+1行表示i号职员的快乐指数Ri。(-128<=Ri<=127)
接下来N-1行,每行输入一对整数L,K。表示K是L的直接上司。
最后一行输入0,0。

输出描述 Output Description

输出最大的快乐指数。

样例输入 Sample Input

7
1
1
1
1
1
1
1
1 3
2 3
6 4
7 4
4 5
3 5
0 0

样例输出 Sample Output

5

数据范围及提示 Data Size & Hint

各个测试点1s

#include<cstdio>
#include<algorithm>
#include<cstring>
#define long long ll
using namespace std;
const int N=6010;
int map[N];
struct node
{
    int to,next;
}e[N*2];
int boss[N]={0};
int first[N],cnt=0;
int is_boss;
int f[N][5];

void insert(int v,int u)
{
     e[++cnt].to=u;e[cnt].next=first[v];first[v]=cnt;
     //printf("===========\n%d %d %d\n==========\n",e[cnt].to,e[cnt].next,first[cnt]);
}

void dfs(int x)
{
        f[x][0]=0;f[x][1]=map[x];
        for(int i=first[x];i;i=e[i].next)
        {
            int p=e[i].to;
            dfs(p);
            f[x][0]+=max(f[p][0],f[p][1]);
            f[x][1]+=f[p][0];
            //printf("%d %d\n",f[x][0],f[x][1]);
        }
}    

int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&map[i]);
    int v,u;
    while(1)
    {
        scanf("%d %d",&v,&u);
        if(v+u==0) break;
        boss[v]++;
        insert(u,v);
    }
    //printf("-------------------------\n");
    for(int i=1;i<=n;i++) if(!boss[i]) {is_boss=i;break;}
    //printf("%d \n",is_boss);
    dfs(is_boss);
    printf("%d",max(f[is_boss][1],f[is_boss][0]));
    return 0;
}

转移方程:

f[]中的0代表不选,1代表选;

谢谢姚老教导(again);

-----------------------------------------

时间: 2025-01-02 17:00:43

动态规划 树型DP的相关文章

HDU1561 The more, The Better(树型DP)

题目是有n个存有宝藏的城堡,攻克任何一个城堡都需要先攻克0个或其他1个城堡,问攻克m个城堡最多能得到多少宝藏. 题目给的城堡形成一个森林,添加一个超级根把森林连在一起就是树了,那么就考虑用树型DP: dp[u][m]表示以u结点为根的子树攻克m个结点的最大价值 但是这样转移太难了,根是从每个孩子通过各自分配若干的城堡去攻克转移的,一个排列组合数,阶乘,是指数级的时间复杂度! 看了题解,原来这是依赖背包,没看背包九讲..不过网上的博客似乎没说清楚,事实上这个状态应该是三个维度来表示: dp[u][

POJ3659 Cell Phone Network(树上最小支配集:树型DP)

题目求一棵树的最小支配数. 支配集,即把图的点分成两个集合,所有非支配集内的点都和支配集内的某一点相邻. 听说即使是二分图,最小支配集的求解也是还没多项式算法的.而树上求最小支配集树型DP就OK了. 树上的每个结点作为其子树的根可以有三个状态: 不属于支配集且还没被支配 不属于支配集但被其孩子支配 属于支配集 那么就是用dp[u][1\2\3]来表示动归的状态. 123转移该怎么转移就怎么转移..最后的结果就是min(dp[root][2],dp[root][3]). 要注意的是对于有些结点前2

HDU_1561_The more, The Better_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1561 The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 7031    Accepted Submission(s): 4121 Problem Description ACboy很喜欢玩一种战略游戏,

HDU_1520_Anniversary party_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1520 Anniversary party Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8233    Accepted Submission(s): 3574 Problem Description There is going to b

二叉苹果树(树型DP+背包)

二叉苹果树 有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点).这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1. 我们用一根树枝两端连接的结点的编号来描述一根树枝的位置.下面是一颗有4个树枝的树: 2   5 \  / 3  4 \  / 1 现在这颗树枝条太多了,需要剪枝.但是一些树枝上长有苹果. 给定需要保留的树枝数量,求出最多能留住多少苹果. 程序名:apple 输入格式: 第1行2个数,N和Q(1<=Q<= N,1<N<=

HDU_1011_Starship Troopers_树型dp

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1011 Starship Troopers Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 16276    Accepted Submission(s): 4335 Problem Description You, the leader o

【HDOJ 5834】Magic boy Bi Luo with his excited tree(树型DP)

[HDOJ 5834]Magic boy Bi Luo with his excited tree(树型DP) Magic boy Bi Luo with his excited tree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) Problem Description Bi Luo is a magic boy, he also has a migic tree,

【POJ 2486】 Apple Tree(树型dp)

[POJ 2486] Apple Tree(树型dp) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8981   Accepted: 2990 Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to an apple tree. There are N nodes in the tree. Each

[HAOI2010][BZOJ2427] 软件安装|tarjan|树型dp

2427: [HAOI2010]软件安装 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 463  Solved: 194[Submit][Status][Discuss] Description 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(