洛谷P1352 没有上司的舞会(DP)

题意分析

树形DP入门题目。
树形DP其实和普通的DP区别就在于转移的方式。
普通的DP的状态转移是在一张表上,表的坐标表示不同的状态。而树形DP由于其特殊性,即题目中描述的关系满足树形的结构,所以利用树形结构进行状态的转移。
由于是在树上进行状态转移,所以DFS是必不可少的。

对于这道题来说,关系正好是一棵树,并且可以明确的是,如果选择了父节点,那么其子节点就不能选择;如果不选择其父节点,那么就子节点就有选和不选两种决策,取最大值即可。状态转移方程呼之而出。用 dp[rt][0] d p [ r t ] [ 0 ] 来表示不选择 rt r t 这个节点,而用 dp[rt][1] d p [ r t ] [ 1 ] 来表示选择这个节点,状态转移方程如下:

dp[rt][0]+=max(dp[son][0],dp[son][1]) d p [ r t ] [ 0 ] + = m a x ( d p [ s o n ] [ 0 ] , d p [ s o n ] [ 1 ] )
dp[rt][1]+=dp[son][0] d p [ r t ] [ 1 ] + = d p [ s o n ] [ 0 ]

代码总览

#include
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;iint 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;
}

你可能感兴趣的:(算法---动态规划)