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

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

 

Sol

首先需要根据题目条件把苹果树建出来

 

容易想到f[i][j]表示以i结点为根的苹果树上保留j个结点所能保留的最大苹果树

需要注意的是f[i][j]包括i结点(根)与它的父亲联结的枝条上的苹果

转移的话就枚举i的第一个子结点保留的结点数k,那么另一个子结点保留的就是j-k-1

 

这题的转移还是很简单的,因为它是二叉的,只有二叉鸭

如果是多叉呢? 那不就和一样了嘛,是一个树形背包问题 树形DP+分组背包

和选课略有不同的是苹果在边上,而课程在结点上

 

Code

(是很久以前的code,好像和现在风格不太一样QwQ,大概是因为以前不压行??)

1 #include
2 #include
3 #include
4 using namespace std; 5 int dp[110][110]; 6 int a[110]; 7 int map[110][110]; 8 int lc[110],rc[110]; 9 int n,q;10 void build(int now)11 {12 for(int i=1;i<=n;i++)13 {14 if(map[now][i]>=0) 15 {16 lc[now]=i;17 a[i]=map[now][i];18 map[now][i]=-1;map[i][now]=-1;19 build(i);20 break;21 }22 }23 for(int i=1;i<=n;i++)24 {25 if(map[now][i]>=0)26 {27 rc[now]=i;28 a[i]=map[now][i];29 map[now][i]=-1;map[i][now]=-1;30 build(i);31 break;32 }33 }34 }35 int DP(int now,int data)36 {37 if(dp[now][data]) return dp[now][data];38 if(data==0) return 0;39 if(lc[now]==0&&rc[now]==0) return a[now];40 for(int i=0;i<=data-1;i++)41 {42 dp[now][data]=max(dp[now][data],DP(lc[now],i)+DP(rc[now],data-i-1)+a[now]);43 }44 return dp[now][data];45 }46 int main()47 {48 cin>>n>>q;q++;49 memset(map,-1,sizeof(map));50 for(int i=1;i
>x>>y>>z;53 map[x][y]=map[y][x]=z;54 }55 build(1);56 cout<
没有注释版 Code
1 #include
2 #include
3 #include
4 using namespace std; 5 int dp[110][110]; //dp[i][j] 以i为根节点的树上保留j个节点的最大苹果数 6 //注意dp[i][j]包括根节点和它的父亲的边上的苹果数 7 //保留i个节点包括根节点 也就是说它的孩子结点只能保留i-1个 8 int a[110]; //a[i]节点i与它的父亲相连的边上的苹果数 9 int map[110][110]; //map[i][j]:i与j连接的边上的苹果树 若无边则初始化为-1 10 int lc[110],rc[110]; //lc[i]:i的左孩子 rc[]:右孩子 11 int n,q;12 void build(int now) //建树 13 {14 for(int i=1;i<=n;i++)15 {16 if(map[now][i]>=0) //找到第一个与now相连的节点作为它的左孩子 17 {18 lc[now]=i; 19 a[i]=map[now][i];20 map[now][i]=-1;map[i][now]=-1; //记录过了 21 build(i); 22 break; //找到一个就退出循环 进入下一个循环寻找右孩子 23 }24 }25 for(int i=1;i<=n;i++)26 {27 if(map[now][i]>=0)28 {29 rc[now]=i;30 a[i]=map[now][i];31 map[now][i]=-1;map[i][now]=-1;32 build(i);33 break;34 }35 }36 }37 int DP(int now,int data) //以now为根节点的树上保留data个结点 38 {39 if(dp[now][data]) return dp[now][data]; //搜过了 40 if(data==0) return 0; 41 if(lc[now]==0&&rc[now]==0) return a[now]; 42 for(int i=0;i<=data-1;i++)43 {44 dp[now][data]=max(dp[now][data],DP(lc[now],i)+DP(rc[now],data-i-1)+a[now]);45 }46 return dp[now][data];47 }48 int main()49 {50 cin>>n>>q;q++; //q++!!! 因为输入的q是保留q条边 即为保留q+1个结点 51 memset(map,-1,sizeof(map)); //初始化 52 for(int i=1;i
>x>>y>>z;55 map[x][y]=map[y][x]=z; //先邻接矩阵储存 56 }57 build(1); //以1为根结点建树 其实就是为了记录每个点的左右孩子以及它与自己父亲相连的边上的结点数 58 cout<
详细注释版 Code

 

转载于:https://www.cnblogs.com/forward777/p/11007840.html

你可能感兴趣的文章
项目初尝试——α迭代感想
查看>>
dgraph实现基本操作
查看>>
[Arduino] 基于Xbee Pro和网络技术的智能公交系统设计
查看>>
My97DatePicker日历控件配置
查看>>
HDU 3586-Information Disturbing(树形dp)
查看>>
《超越CSS:web设计精髓》的读后感
查看>>
团队项目第一阶段冲刺站立会议09
查看>>
团队项目第二阶段冲刺站立会议03
查看>>
Python 错误和异常小结
查看>>
sass基础
查看>>
关于Unity中特殊目录
查看>>
360wifi提取版
查看>>
关于Unity遇到的问题
查看>>
jQuery---ajax
查看>>
hdu 1270
查看>>
存储过程笔记
查看>>
AtCoder Grand Contest 017 迟到记
查看>>
CodeForces - 858A k-rounding
查看>>
CF 622F (拉格朗日插值)
查看>>
javascript变量类型转换(简单记几个)
查看>>