
【SSL】1605&【洛谷】P2015二叉苹果树
发布日期:2021-05-07 09:21:37
浏览次数:36
分类:原创文章
本文共 1624 字,大约阅读时间需要 5 分钟。
【SSL】1605&【洛谷】P2015二叉苹果树
Time Limit:1000MS Memory Limit:65536K
Description
有一棵苹果树,如果树枝有分叉,一定是分2叉(就是说没有只有1个儿子的结点)
这棵树共有N个结点(叶子点或者树枝分叉点),编号为1-N,树根编号一定是1。
我们用一根树枝两端连接的结点的编号来描述一根树枝的位置。下面是一颗有4个树枝的树
2 5
\ /
3 4
\ /
1
现在这颗树枝条太多了,需要剪枝。但是一些树枝上长有苹果。
给定需要保留的树枝数量,求出最多能留住多少苹果。
Input
第1行2个数,N和Q(1<=Q<= N,1
Output
一个数,最多能留住的苹果的数量。
Sample Input
5 21 3 11 4 102 3 203 5 20
Sample Output
21
思路
我们设ma[x][y]为边的值,因为树是双向的,所以要再记录ma[y][x]。
设tree[v,1]为节点v的左子树,tree[v,2]为节点v的右子树,然后我们再递归建树。
定义f[i][j]表示以i为节点的根保留j条边的最大值
f[v][k]=max(f[v][k],(f[tree[v][1]][i]+f[tree[v][2]][k-i-1]+num[v]))
我们枚举i就可以了,用记忆化搜索的形式(dfs)来具体实现。
F[1][Q+1]就是答案。
因为题目中给的是边的权值,而我们在处理时将每条边的权值全赋给其所连的父节点和子节点中的子节点(将关于边的问题转化为关于点的问题),所以最后是Q+1,表示点的数目。
代码
#include<iostream>#include<cstdio>#include<cstring>using namespace std;long long a[110][110],f[110][110],l[110],r[110],num[110],n;void maketree(long long v);void build(long long x,long long y,long long o){ if(o)r[x]=y; else l[x]=y; num[y]=a[x][y],a[x][y]=a[y][x]=-1,maketree(y); return;}void maketree(long long x){ bool lr=1; for(long long i=1;i<=n;i++) if(a[x][i]>-1) { lr=!lr,build(x,i,lr); if(lr)return; } return;}long long DP(long long x,long long y){ if(f[x][y]>-1)return f[x][y]; if(y==0)return f[x][y]=0; if(!l[x]&&!r[x])return f[x][y]=num[x]; for(long long k=0;k<y;k++)f[x][y]=max(f[x][y],DP(l[x],k)+DP(r[x],y-k-1)+num[x]); return f[x][y];}int main(){ ios::sync_with_stdio(false); long long q,i,j,x,y,t; memset(f,-1,sizeof(f)),memset(a,-1,sizeof(a)); for(cin>>n>>q,i=1;i<n;i++)cin>>x>>y>>t,a[x][y]=a[y][x]=t; maketree(1),cout<<DP(1,q+1); return 0;}
发表评论
最新留言
留言是一种美德,欢迎回访!
[***.207.175.100]2025年04月06日 21时53分51秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
【△重点△】LeetCode - 4. 寻找两个正序数组的中位数——二分查找
2019-03-04
LeetCode - 5. 最长回文子串——字符串、动态规划
2019-03-04
【BFS】——LeetCode - 752. 打开转盘锁
2019-03-04
【快慢指针】——LeetCode - 287. 寻找重复数
2019-03-04
剑指 Offer 36. 二叉搜索树与双向链表——DFS
2019-03-04
【滑动窗口法】—— 438. 找到字符串中所有字母异位词
2019-03-04
【牛客网 - 华为机试】HJ106 字符串逆序
2019-03-04