树形背包DP的两种优化方式——vijos1676、codeforces815c


1.O(nm)——vijos1676陶陶吃苹果

背景
陶陶很喜欢吃苹果。

描述
curimit知道陶陶很喜欢吃苹果。于是curimit准备在陶陶生日的时候送给他一棵苹果树。

curimit准备了一棵这样的苹果树作为生日礼物:这棵苹果树有n个节点,每个节点上有c[i]个苹果,这棵树高度为h。

可是,当curimit把这棵树给陶陶看的时候,陶陶却说:“今年生日不收礼,收礼只收节点数减高度不超过k的苹果树。”这下curimit犯难了,curimit送来的树枝繁叶茂,不满足节点数-高度≤k。于是curimit决定剪掉一些枝条,使得修剪过后的树满足节点数-高度≤k,但是curimit又想保留尽量多的苹果数目。curimit想请你帮他算算经过修剪后的树最多能保留多少个苹果。

注:
一, 节点1为树根,不能把它剪掉。

二, 1个节点的树高度为1。


对于一课剪枝完满足条件的树,树的size最大就是m+树的最长链,换种说法就是取m个结点+一条链求怎么样最大化收益,同时还要满足树形背包dp的选了父节点才能选子节点的条件。
易知,选的链越长越好,所以答案所包含的那条最长链一定是跟到叶子结点的。
使用论文里的状态设置方式,dp[u][i]表示考虑了u结点左边的所有节点和所有子节点,花费i所能得到的最大收益。那么对于任意叶节点v,dp[v][i]就表示v结点左边结点中花费i的最大收益,从左往右dfs一遍再从右往左dfs一遍,得到两个dp数组,就能枚举叶节点和左边的花费得到答案。

#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn=4005;
const int maxm=505;
const int maxe=maxn*2;
const ll mod=1e9+7;
const int inf=0x3f3f3f3f;
int n,m,k;
int dpl[maxn][maxm];
int dpr[maxn][maxm];
int c[maxn];
vector<
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值