当前位置: 首页 > news >正文

20251109 树状DP总结

引子

树状DP,就是在树上进行动态规划,由于树的特殊递归属性,所以树状DP都是在树上进行的。

树状DP可以分成两种:

  1. 兄弟节点间无相互约束
  2. 兄弟节点间有相互约束

第一种,兄弟节点间无相互约束的树状DP,这种树状DP意味着兄弟节点之间互不干扰,你干你的,他干他的。这种树状DP的经典例题有 洛谷 没有上司的舞会。

第二种,兄弟节点间有相互约束的树状DP,这种树状DP意味着兄弟节点间会互相干扰,就像给这几个兄弟节点分苹果,你分得多一点别人就分的少一点,你分得少一点别人就分的多一点。这种树状DP的经典例题有 洛谷 二叉苹果树。

P1352 没有上司的舞会

题目传送门

简化题意:有 n 个点,他们的从属关系用一颗树来表示,父结点是子结点的直接上司。每个点有一个点权,求拿出若干个点且这若干个点的任意两点无从属关系的最大点权和。

我们定义状态 dp[i][0/1]dp[i][0/1]dp[i][0/1] 表示以节点𝑖为根的子树的最大点权值。其中:

  • 第二维取0表示节点 i 不参加舞会
  • 第二维取1表示节点 i 参加舞会

状态转移方程如下(设 v 为 x 的子节点):

  1. 当 x 不参加舞会时:
    dp[x][0]+=max(dp[v][1],dp[v][0]);dp[x][0] += max(dp[v][1],dp[v][0]);dp[x][0]+=max(dp[v][1],dp[v][0]);
    即子节点可以自由选择是否参加
  2. 当 x 参加舞会时:
    dp[x][1]+=dp[v][0];dp[x][1] += dp[v][0];dp[x][1]+=dp[v][0];
    此时所有子节点都不能参加

我们用DFS遍历这棵树,在回溯时更新每个节点的DP。

#include<bits/stdc++.h>
using namespace std;
int r[6005],dp[6005][2];
vector<int> E[6005];
void dfs(int x,int fa){dp[x][1]=r[x];for(int i=0;i<E[x].size();i++){int v=E[x][i];if(v==fa)continue;dfs(v,x);dp[x][0]+=max(dp[v][1],dp[v][0]);dp[x][1]+=dp[v][0];}
}
int main(){int n;cin>>n;for(int i=1;i<=n;i++){cin>>r[i];}for(int i=1;i<n;i++){int u,v;cin>>u>>v;E[u].push_back(v);E[v].push_back(u);}dfs(1,0);cout<<max(dp[1][0],dp[1][1]);return 0;
}

P2015 二叉苹果树

题目传送门

题意:给定一棵树,n个点,有边权,至少保留q条边,求最大边权和。

1.q条边分到左子树多,那么右子树就少,兄弟节点间有数量约束,考虑第二类树型DP。

2.状态:dp[i][j] 表示以 i 为根节点的子树保留至多 j 条边的最大边权和。

3.答案: dp[1][q]

4.状态转移:

int v=E[x][i].v,w=E[x][i].w;
if(v==fa)continue;
dfs(v,x);
sz[x]+=sz[v];
for(int j=min(q,sz[x]);j>=0;j--){for(int k=0;k<=min(j-1,sz[v]);k++){dp[x][j]=max(dp[x][j],dp[v][k]+dp[x][j-k-1]+w);}
}

5.初始状态:dp[x][0]=0dp[x][0]=0dp[x][0]=0

#include<bits/stdc++.h>
using namespace std;
struct node{int u,v,w;
};
vector<node> E[105];
int n,q,sz[105],dp[105][105];
void dfs(int x,int fa){sz[x]=1;for(int i=0;i<E[x].size();i++){int v=E[x][i].v,w=E[x][i].w;if(v==fa)continue;dfs(v,x);sz[x]+=sz[v];for(int j=min(q,sz[x]);j>=0;j--){for(int k=0;k<=min(j-1,sz[v]);k++){dp[x][j]=max(dp[x][j],dp[v][k]+dp[x][j-k-1]+w);}}}
}
int main(){cin>>n>>q;for(int i=1;i<n;i++){int u,v,w;cin>>u>>v>>w;E[u].push_back({u,v,w});E[v].push_back({v,u,w});}dfs(1,0);cout<<dp[1][q];return 0;
}
http://www.dtcms.com/a/614399.html

相关文章:

  • C语言编译器出现Bug | 如何解决C语言编译器常见问题
  • 做淘宝客网站php青岛网站推广企业
  • 第九篇 扫雷游戏 上(末版·精简)
  • ⚡️2025-11-15GitHub日榜Top5|热点智能推送工具
  • python做项目的网站国家标准下载网免费
  • 网站建设服务费属于基于asp网站开发 论文
  • 高斯数据库 (GaussDB) 使用指南
  • 安徽茶叶网站建设网站抽奖模块怎么做
  • 建立自己的影视网站快手免费推广软件
  • 织梦网站调整网店如何推广自己的产品
  • 构建AI智能体:九十五、YOLO视觉大模型入门指南:从零开始掌握目标检测
  • 【文档】Aerial CUDA-Accelerated RAN , Aerial cuBB 部分
  • 育儿心理学
  • 建网站公司 快云淘宝客优惠券的网站是怎么做的
  • 黑马Redis A-基础
  • 一小时速通Pytorch之神经网络相关知识(三)
  • 帝国cms小说网站模板清美未来广告设计公司
  • 从编译角度来理解匿名函数与闭包
  • 【C++】3:函数重载、内联函数和nullptr
  • 如何做旅游网站的思维导图wordpress无法访问上传的图面
  • 赣州网站推广广州市天河区发布
  • python函数(三)———学员管理系统
  • 张北县网站建设广州网站网站建设
  • 电磁场中的静态与定态两个概念
  • 南京网站建设 小程序phpcms网站模板下载
  • 昌邑网站建设公司国外有什么做网站的软件吗
  • Qt QTreeView深度解析:从原理到实战应用
  • 建设网站需要哪些经营范围免费发帖推广的平台
  • 用C语言编译好玩的程序 | 探索编程世界的奇妙乐趣
  • 【开发备忘】GeoServer相关两则:发布时间维ImageMosaic+客户端WMS样式