题意分析
树形DP入门题目。
树形DP其实和普通的DP区别就在于转移的方式。
普通的DP的状态转移是在一张表上,表的坐标表示不同的状态。而树形DP由于其特殊性,即题目中描述的关系满足树形的结构,所以利用树形结构进行状态的转移。
由于是在树上进行状态转移,所以DFS是必不可少的。
对于这道题来说,关系正好是一棵树,并且可以明确的是,如果选择了父节点,那么其子节点就不能选择;如果不选择其父节点,那么就子节点就有选和不选两种决策,取最大值即可。状态转移方程呼之而出。用dp[rt][0]dp[rt][0] 来表示不选择rtrt 这个节点,而用dp[rt][1]dp[rt][1] 来表示选择这个节点,状态转移方程如下:
dp[rt][0]+=max(dp[son][0],dp[son][1])dp[rt][0]+=max(dp[son][0],dp[son][1])
dp[rt][1]+=dp[son][0]dp[rt][1]+=dp[son][0]
代码总览
#include<bits/stdc++.h>
using namespace std;
const int nmax = 6050;
int dp[nmax][2];
int a[nmax];
int ind[nmax];
int n;
vector<int> v[nmax];
void dfs(int rt){
dp[rt][0] = 0;
dp[rt][1] = a[rt];
for(int i = 0;i<v[rt].size();++i){
int tar = v[rt][i]; dfs(tar);
dp[rt][0] += max(dp[tar][0], dp[tar][1]);
dp[rt][1] += dp[tar][0];
}
return;
}
int main(){
scanf("%d",&n);
for(int i = 1;i<=n;++i) scanf("%d",&a[i]);
int x,y;
while(scanf("%d %d",&x,&y) &&(x!=0 && y!=0)){
v[y].push_back(x);
ind[x]++;
}
int root = 0;
for(int i = 1;i<=n;++i){
if(ind[i] == 0){
root = i;
dfs(root);
break;
}
}
// printf("root %d\n",root);
printf("%d\n",max(dp[root][1],dp[root][0] ) ) ;
return 0;
}
本文介绍了一道树形动态规划的入门题目,通过DFS遍历树结构实现状态转移。文章详细解析了状态转移方程,并提供了完整的代码示例。
1057

被折叠的 条评论
为什么被折叠?



