POJ 2486 Apple Tree(树形DP)
树形DP很弱啊,开始看题,觉得貌似挺简单的,然后发现貌似还可以往回走...然后就不知道怎么做了...
看看了题解http://www.cnblogs.com/wuyiqi/archive/2012/01/09/2316758.html画画题解中的三种情况,还是可以理解的。
设dp[0][s][j]表示从s(当前根节点)出发,走 j 步,回到s所能获得的最大权值
dp[1][s][j]表示从s(当前根节点)出发,走j步,不回到s所能获得的最大权值
现在我们就可以分配背包容量了:父节点与子节点分配背包容量,从而设计出状态转移方程
主要思想:
s返回,t返回
s不返回,t返回(走向t子树,t子树返回之后走向s的其他子树,然后不回到s)
s返回,t不返回(遍历s的其他子树后返回s,返回之后走向t子树,然后不回到t)
没有都不返回,肯定有一方有一个返回的过程,再去另一边的子树的
总结起来一句话,要么去s的其他子树呆着,要么去t子树呆着,要么回到s点
1、在t子树返回,其他子树也返回,即回到当前根节点s
2,、不返回根节点,但在t子树返回,即相当于从t出发走k步返回t的最优值 加上 从s出发走j-k步到其他子树不返回的最优值,中间有s与t连接起来,其实就等于从s出发遍历t子树后(dp[0][t][k])又回到s(这一步多了中间的来回两步),再走出去(其他子树)【dp[1][s][j-k]】,不回来
3、不返回根节点,在t子树也不返回,等价于从s出发遍历其他子树,回到s(dp[0][s][j-k]),再走向t子树,不回到t(dp[1][t][k]),这个过程s-t只走了一步
dp[0][s][j+2]=Max(dp[0][s][j+2],dp[0][t][k]+dp[0][s][j-k]);//从s出发,要回到s,需要多走两步s-t,t-s,分配给t子树k步,其他子树j-k步,都返回
dp[1][s][j+2]=Max(dp[1][s][j+2],dp[0][t][k]+dp[1][s][j-k]);//不回到s(去s的其他子树),在t子树返回,同样有多出两步
dp[1][s][j+1]=Max(dp[1][s][j+1],dp[1][t][k]+dp[0][s][j-k]);//先遍历s的其他子树,回到s,遍历t子树,在当前子树t不返回,多走一步
#include <cstdio> #include <cstring> #include <iostream> #include <cmath> #include <algorithm> using namespace std; #define N 200100 #define LL __int64 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct node { int u,v,next; }edge[201]; int dp[201][201][2]; int first[201]; int p[201]; int t,n,k; void CL() { t = 1; memset(first,-1,sizeof(first)); memset(dp,0,sizeof(dp)); } void add(int u,int v) { edge[t].u = u; edge[t].v = v; edge[t].next = first[u]; first[u] = t ++; } void dfs(int rt) { int i,j,son,v; for(i = 0;i <= k;i ++) dp[rt][i][0] = dp[rt][i][1] = p[rt]; for(i = first[rt];i != -1;i = edge[i].next) { son = edge[i].v; dfs(son); for(j = k;j >= 0;j --) { for(v = 0;v <= j;v ++) { dp[rt][j+2][0] = max(dp[rt][j+2][0],dp[rt][v][0]+dp[son][j-v][0]); dp[rt][j+1][1] = max(dp[rt][j+1][1],dp[rt][v][0]+dp[son][j-v][1]); dp[rt][j+2][1] = max(dp[rt][j+2][1],dp[rt][v][1]+dp[son][j-v][0]); } } } } int main() { int i,u,v; while(scanf("%d%d",&n,&k)!=EOF) { CL(); for(i = 1;i <= n;i ++) scanf("%d",&p[i]); for(i = 1;i < n;i ++) { scanf("%d%d",&u,&v); add(u,v); } dfs(1); printf("%d\n",dp[1][k][1]); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 解答了困扰我五年的技术问题
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· 用 C# 插值字符串处理器写一个 sscanf
· Java 中堆内存和栈内存上的数据分布和特点
· 开发中对象命名的一点思考
· 为什么说在企业级应用开发中,后端往往是效率杀手?
· DeepSeek 解答了困扰我五年的技术问题。时代确实变了!
· 本地部署DeepSeek后,没有好看的交互界面怎么行!
· 趁着过年的时候手搓了一个低代码框架
· 推荐一个DeepSeek 大模型的免费 API 项目!兼容OpenAI接口!
2012-07-21 HDU 4217 Data Structure?(树状数组+二分)
2012-07-21 HDU 1506 Largest Rectangle in a Histogram(DP)
2012-07-21 HDU 2546 饭卡(贪心+DP)
2012-07-21 URAL 1306. Sequence Median(优先队列)
2012-07-21 HDU 1425 sort(堆排序)