这周是计划学习树形dp的,但是因为复习其他的事情耽误了点计划,后面又突然出了事就急忙收拾行李改了车票,到今天凌晨才刚到家
树形dp首先是一些比较简单的题目就像上次提到的poj 2342 Anniversary party,根据不同情况分为不同节点,由节分分成不同的叶,如
dp[node][1] += dp[i][0];//上司来,下属不来
dp[node][0] +=max(dp[i][1],dp[i][0]);//上司不来,下属来、不来
这种是比较简单的分情况,
也还有其他的比较难的本来树的内容就有很多,像是什么二叉树,树的遍历什么都可以结合动规进行
【SSOI562】二叉苹果树
#include<bits/stc++.h>
using namespace std;
const int ee=105;
int n,q;
int tree[ee][5]={0},ma[ee][ee]={0},num[ee]={0},f[ee][ee]={0};
void preproccess()
{
for(int i=0;i<=n;i++)
for(int j=0;j<=n;j++)
{
ma[i][j]=-1;
ma[j][i]=-1;
}
}
void maketree(int v);
void build(int x,int y,int lor)//lor means left or right
{
num[y]=ma[x][y];
tree[x][lor]=y;
ma[x][y]=-1;ma[y][x]=-1;
maketree(y);
}
void maketree(int v)
{
int lr=0;
for(int i=0;i<=n;i++)
if(ma[v][i]>=0)//如果分叉了,那么记录
{
lr++; //1 or 2 表示左支还是右支;
build(v,i,lr);//存入并递归
if(lr==2) return;
}
}
void dfs(int v,int k)
{
if(k==0) f[v][k]=0;
else if(tree[v][1]==0 && tree[v][2]==0) f[v][k]=num[v];
else
{
f[v][k]=0;
for(int i=0;i<k;i++)
{
if(f[tree[v][1]][i]==0) dfs(tree[v][1],i);
if(f[tree[v][2]][k-i-1]==0) dfs(tree[v][2],k-i-1);
f[v][k]=max(f[v][k],(f[tree[v][1]][i]+f[tree[v][2]][k-i-1]+num[v]));
}
}
}
int main()
{
cin>>n>>q;
preproccess();
for(int i=0;i<n;i++)
{
int x,y,xy;
scanf("%d%d%d",&x,&y,&xy);
ma[x][y]=xy;
ma[y][x]=xy;
}
//建树;
maketree(1);
dfs(1,q+1);
cout<<f[1][q+1];
return 0;
}
关于树dp 还有很多类型,没有了解,下周还是练习树形dp的题目