隐藏页面特效

[树上背包浅谈]

1|0树上背包


在这个树中选取一定数量的点或边(也可能是其他属性),使得某种与点权或者边权相关的花费最大或者最小。解决这类问题,一般要考虑使用树上背包。

dp[i][j]表示在以i为根的树中选择j个结点所获得的最大值/最小值

有线电视网

#include <cstdio> #include <cstring> #include <iostream> using namespace std; const int maxn = 3005; int n,m,cost[maxn]; int head[maxn],cnt; int dp[maxn][maxn]; struct Edge{ int to,len,next; }edge[maxn]; void add(int u,int v,int w) { cnt ++; edge[cnt].to = v; edge[cnt].len = w; edge[cnt].next = head[u]; head[u] = cnt; return ; } int dfs(int u)//dfs返回的是以u为根节点的树,所包含的叶子结点数 { if(u > n-m) return 1;//说明到了叶子结点 int num = 0; for(int i=head[u];i;i=edge[i].next) { int v = edge[i].to; int nv = dfs(v); num += nv; for(int j=num;j>=0;j--)//类似滚动数组的思想,j要倒着写,这样j是不断变小的,如果j先更新小的,那么大的会被更新过的dp[u][j-k]更新,这是错误的 for(int k=0;k<=min(nv,j);k++) dp[u][j] = max(dp[u][j],dp[u][j-k]+dp[v][k]-edge[i].len); } return num; } int main() { memset(dp,128,sizeof(dp));//求最大值故初始化为最小 scanf("%d%d",&n,&m); for(int i=1;i<=n-m;i++) { int num; scanf("%d",&num); for(int j=1;j<=num;j++) { int a,c; scanf("%d%d",&a,&c); add(i,a,c); } } for(int i=n-m+1;i<=n;i++) { scanf("%d",&cost[i]); dp[i][1] = cost[i];//叶子节点选择自己的值 } for(int i=1;i<=n;i++) dp[i][0] = 0;//所有节点在不选择任何节点的情况下都是0 dfs(1); for(int i=m;i>=0;i--) { if(dp[1][i] >= 0) { printf("%d",i); break; } } return 0; }

__EOF__

本文作者风丨铃
本文链接https://www.cnblogs.com/-Wind-/p/18104244.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   风丨铃  阅读(14)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示