博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P2015 二叉苹果树
阅读量:7143 次
发布时间:2019-06-29

本文共 3764 字,大约阅读时间需要 12 分钟。

题目描述

有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)

这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。

我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树

2 5 \ / 3 4 \ / 1 现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。

给定需要保留的树枝数量,求出最多能留住多少苹果。

输入输出格式

输入格式:

第1行2个数,N和Q(1<=Q<= N,1<N<=100)。

N表示树的结点数,Q表示要保留的树枝数量。接下来N-1行描述树枝的信息。

每行3个整数,前两个是它连接的结点的编号。第3个数是这根树枝上苹果的数量。

每根树枝上的苹果不超过30000个。

输出格式:

一个数,最多能留住的苹果的数量。

输入输出样例

输入样例#1:
5 21 3 11 4 102 3 203 5 20
输出样例#1:
 21
这是一道比较不错的树形DP的题目,
刚开始的时候用贪心乱搞,搞了搞边,搞了搞点,搞了颗树,搞了39分。。。
1 #include
2 #include
3 #include
4 #include
5 using namespace std; 6 const int MAXN=1001; 7 int n,q; 8 int v[MAXN]; 9 int vis[MAXN]; 10 int deep[MAXN]; 11 int read(int & n) 12 { 13 char p='+';int x=0; 14 while(p<'0'||p>'9') 15 p=getchar(); 16 while(p>='0'&&p<='9') 17 x=x*10+p-48,p=getchar(); 18 n=x; 19 } 20 struct node 21 { 22 int u; 23 int v; 24 int w; 25 int nxt; 26 }edge[MAXN]; 27 int num=1; 28 int head[MAXN]; 29 void add_edge(int x,int y,int z) 30 { 31 edge[num].u=x; 32 edge[num].v=y; 33 edge[num].w=z; 34 edge[num].nxt=head[x]; 35 head[x]=num++; 36 } 37 struct deal 38 { 39 int how; 40 int val; 41 int l; 42 }a[MAXN]; 43 void build_tree(int p) 44 { 45 vis[p]=1; 46 for(int i=head[p];i!=-1;i=edge[i].nxt) 47 { 48 if(vis[edge[i].v]==0) 49 { 50 deep[edge[i].v]=deep[p]+1; 51 build_tree(edge[i].v); 52 } 53 54 } 55 } 56 void deal_val(int p,int pre) 57 { 58 vis[p]=1; 59 for(int i=head[p];i!=-1;i=edge[i].nxt) 60 { 61 int will=edge[i].v; 62 if(will!=0&&vis[will]==0&&deep[will]>deep[p]) 63 { 64 a[pre].l++; 65 a[pre].val+=edge[i].w; 66 deal_val(will,pre); 67 } 68 69 70 } 71 } 72 int comp(const deal & a ,const deal & b) 73 { 74 if(a.val!=b.val) 75 return a.val
贪心

后来看题解用树形DP,

对于每一个节点,我们可以枚举它相连的边,

用dp[i][j]表示第i个节点,在他的子节点中保留j条树枝的最大值

那么我们可以枚举节点和j,当然,在枚举j的时候我们需要同时枚举一个k

我们可以想一下,该节点i需要保留j条边,那么我们取他的最大值得时候,可以对他相连的节点进行DP,

如果j=5,这时候需要保留5条边,

因为整个树是二叉树,所以说,他的相连的一条边所能删除的最大数就是4(相连的线段一定会删除)

那么k的范围:0--4

动态转移方程:   

dp[u][j]=max(dp[u][j],dp[u][j-k-1]+dp[will][k]+edge[i].w);

 

1 #include
2 #include
3 #include
4 #include
5 using namespace std; 6 const int MAXN=1001; 7 int n,q; 8 int v[MAXN]; 9 int vis[MAXN];10 int deep[MAXN];11 int dp[MAXN][MAXN];12 int read(int & n)13 {14 char p='+';int x=0;15 while(p<'0'||p>'9')16 p=getchar();17 while(p>='0'&&p<='9')18 x=x*10+p-48,p=getchar();19 n=x;20 }21 struct node22 {23 int u;24 int v;25 int w;26 int nxt;27 }edge[MAXN];28 int num=1;29 int head[MAXN];30 void add_edge(int x,int y,int z)31 {32 edge[num].u=x;33 edge[num].v=y;34 edge[num].w=z;35 edge[num].nxt=head[x];36 head[x]=num++;37 }38 int dfs(int u,int fa)39 {40 int ans=0;41 for(int i=head[u];i!=-1;i=edge[i].nxt)42 {43 int will=edge[i].v;44 if(will==fa)45 continue;46 ans+=dfs(will,u)+1;47 for(int j=min(q,ans);j>=1;j--)48 {49 for(int k=min(j,ans)-1;k>=0;k--)50 {51 dp[u][j]=max(dp[u][j],dp[u][j-k-1]+dp[will][k]+edge[i].w);52 }53 }54 }55 return ans; 56 }57 int main()58 {59 read(n);read(q);60 for(int i=1;i<=n;i++)61 head[i]=-1;62 for(int i=1;i<=n-1;i++)63 {64 int x,y,z;65 read(x);read(y);read(z);66 add_edge(x,y,z);67 add_edge(y,x,z);68 }69 dfs(1,0);70 cout<

 

转载地址:http://hlgrl.baihongyu.com/

你可能感兴趣的文章
让IE和Chrome都以隐身模式启动
查看>>
npm install --save 与 npm install --save-dev 的区别
查看>>
hibernate和jdbc的区别 优缺点
查看>>
斯坦福大学机器学习第一课“引言(Introduction)”
查看>>
MAC OS环境下搭建基于Python语言的Selenium2自动化测试环境
查看>>
Web端五子棋的实现之所遇到的问题
查看>>
gedit增加对指定文件格式(如qml)的识别和启用合适的语法高亮
查看>>
sql字符串包含单引号
查看>>
一句话评论设计模式六大原则【转】
查看>>
如何使用临时文件
查看>>
【原创】关于ARM的22个常用概念介绍
查看>>
【SICP归纳】3 层次性数据和符号数据
查看>>
Docker(五)安装Fastdfs
查看>>
4.9Python数据处理篇之Matplotlib系列(九)---子图分布
查看>>
高德底图 根据行政区域名 加载边界到地图中
查看>>
由后序遍历结果构造二叉查找树 && 二叉查找树链表化
查看>>
Cgroup blkio简介和测试(使用fio测试)
查看>>
VBA练习-复杂一点
查看>>
MyPython-->进阶篇-->类
查看>>
unity remote 连接设置
查看>>