ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

树形dp学习笔记

2021-11-27 13:35:11  阅读:166  来源: 互联网

标签:int 笔记 树形 MAXN dfs include ri dp


主要总结一下树形dp的一些难点与细节问题。

什么是树形dp

顾名思义,就是长得像树结构的dp,在树上进行的dp。

而树形dp有一个比较套路化的状态定义,就是定义 \(dp[i]\) 表示以 \(i\) 为根结点的子树的最大/最小值。

一般的树形dp用dfs实现。

裸树形dp

这里推荐几道比较裸的树形dp:

1.P1122 最大子树和

2.P1352 没有上司的舞会这道题很重要,它代表了一类带分类的树形dp,即多一维记录这个状态的一些信息(因为会有影响)

3.P2016 战略游戏

4.P1131 [ZJOI2007] 时态同步有难度的裸题(

5.P2585 [ZJOI2006]三色二叉树和没有上司的舞会有点像的一道题

具体不详细讲,给一个模板(最大子树和)

int dfs(int x,int fa){//为无根树就多了一个fa
	dp[x]=a[x];
	for(ri i=0;i<T[x].size();i++){
		int y=T[x][i];
		if(y==fa)continue;
		dfs(y,x);
		if(dp[y]>0)dp[x]+=dp[y];
	}
	ans=max(ans,dp[x]);
}

树上背包

这个详细地讲一下吧。

树上背包可以说是有依赖性的dp,因为它的子树与子树之间的 \(dp\) 值是有关系的。

于是我们可以把它看作一个背包来处理。

1.P2015 二叉苹果树

珂爱的小模板。

树上背包有三重循环,分别为子节点,容量,和给每一个子树分配的容量。

注意是无根树!

int dfs(int x,int fa){
	int sum=0;
	for(ri i=0;i<T[x].size();i++){
		int y=T[x][i].pos;
		if(y==fa)continue;
		sum=sum+dfs(y,x)+1;
		for(ri j=min(sum,q);j>=0;j--){//容量 
			for(ri k=0;k<=j-1;k++){//分配的树枝数量 
				dp[x][j]=max(dp[x][j],dp[y][k]+dp[x][j-k-1]+T[x][i].w);
			}
		}
	}
	return sum;
}

2.P2014 [CTSC1997]选课

这道题Wrasar印象深刻,因为当时口胡了一个错的代码(连方程都是错的),然后交上去AC了(((

讲一下正解和一些注意的点吧qwq

(1)输出的答案是 \(dfs(0,n+1)\) ,因为建树的时候把所有的没有先修课的课程都算作先修课为0的课。

所以可以把0看作一个根结点,而本来的可以说是很多棵树,有了0就像一个森林了是不是。

(2)初始值设为 \(dp[x][1]=s[x];\) ,其中 \(s\) 用来存对应的学分数。

这个好想吧。

(3)计算结点数的 \(sum\) 要先赋为 \(1\) 。

因为至少有0这个点了(不过是虚拟的)。

(4)方程是 \(dp[x][j]=max(dp[x][j],dp[y][k]+dp[x][j-k]);\) 。

这个也是显然的(

然后就差不多了,代码放一下。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
#define ri register int
using namespace std;
const int MAXN=310;
int n,m,k,s[MAXN],dp[MAXN][MAXN];
struct node{
	int pos,sco;
};
vector <node> T[MAXN];

int dfs(int x,int fa){
	dp[x][1]=s[x];
	int sum=1;
	for(ri i=0;i<T[x].size();i++){
		int y=T[x][i].pos;
		if(y==fa)continue;
		sum+=dfs(y,x);
		for(ri j=min(sum,m);j>=0;j--){
			for(ri k=0;k<=j-1;k++){
				dp[x][j]=max(dp[x][j],dp[y][k]+dp[x][j-k]);
			}
		}
	}
	return sum;
}

int main() {
	ios::sync_with_stdio(false);
	cin>>n>>m;
	m++;
	for(ri i=1;i<=n;i++){
		cin>>k>>s[i];
		node cur={i,s[i]};
		T[k].push_back(cur);
	}
	dfs(0,n+1);
	cout<<dp[0][m];
	return 0;
}

3.P1272 重建道路

这道题不难,只是要注意容量至少是 \(2\) ,分配的容量至少为 \(1\) 。

注意输出需要循环找。

dp部分:

int dfs(int x){
	dp[x][1]=out[x];
	int sum=1;
	for(ri i=0;i<T[x].size();i++){
		int y=T[x][i];
		int tmp=dfs(y);
		sum+=tmp;
		for(ri j=min(sum,p);j>=2;j--){
			for(ri k=1;k<=min(j-1,tmp);k++){
				dp[x][j]=min(dp[x][j],dp[y][k]+dp[x][j-k]-1);
			}
		}
	}
	return sum;
}

输出部分:

ans=dp[1][p];
for(ri i=2;i<=n;i++)ans=min(ans,dp[i][p]+1);
cout<<ans;

4.P1273 有线电视网

这道题需要一个铺垫:P1510 精卫填海

可以吸取精卫填海的思路,就会做这题了(真的真的

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#define ll long long
#define ri register int
using namespace std;
const int MAXN=3010;
int n,m,k,a,c,pay[MAXN],dp[MAXN][MAXN];
struct node{
	int pos,cos;
};
vector <node> T[MAXN];

int dfs(int x){
	dp[x][0]=0;
	if(x>n-m){
		dp[x][1]=pay[x];
		return 1;
	}
	int sum=0;
	for(ri i=0;i<T[x].size();i++){
		int y=T[x][i].pos;
		int tmp=dfs(y);
		sum+=tmp;
		for(ri j=sum;j>=0;j--){
			for(ri k=0;k<=tmp;k++){
				dp[x][j]=max(dp[x][j],dp[x][j-k]+dp[y][k]-T[x][i].cos);
			}
		}
	}
	return sum;
}

int main() {
	ios::sync_with_stdio(false);
	memset(dp,0xcf,sizeof(dp));
	cin>>n>>m;
	for(ri i=1;i<=n-m;i++){
		cin>>k;
		for(ri j=1;j<=k;j++){
			cin>>a>>c;
			node cur={a,c};
			T[i].push_back(cur);
		}
	}
	for(ri i=n-m+1;i<=n;i++)cin>>pay[i];
	dfs(1);
	for(ri i=m;i>=0;i--){
		if(dp[1][i]>=0){
			cout<<i;
			return 0;
		}
	}
	cout<<0;
	return 0;
}

差不多得了.jpg

标签:int,笔记,树形,MAXN,dfs,include,ri,dp
来源: https://www.cnblogs.com/Wrasar/p/15611644.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有