DP毕竟是算法中最精妙的部分,理解并玩得花哨还是需要一定的时间积累

之前对普通的DP也不敢说掌握,只能说略懂皮毛

在学习树形DP 的同时也算是对DP有了更深的理解吧

DP的关键就在于状态的定义以及找转移

首先要考虑清楚状态,状态要能够很好地并且完整地描述子问题

其次考虑最底层的状态,这些状态一般是最简单的情况或者是边界情况

再就是考虑某一个状态能从哪些子状态转移过来,同时还要考虑转移的顺序,确保子问题已经解决

树形DP很多时候就是通过子节点推父亲节点的状态

还是通过题目来加强理解吧

1.HDU 1520

题意:给一棵树,选最多的结点使得选择的结点不存在直接的父子关系

很容易想到一个结点有两个状态:选或者不选

所以自然地想到状态dp[u][0/1]表示u子树内的最佳答案,u的状态为选或者不选

初始化自然是叶子结点dp[u][0]=0,dp[u][1]=w[u]

转移则可以考虑依次考虑

u不选的时候:u的儿子可以任意选或者不选,所以dp[u][0]+=max(dp[v][0],dp[v][1])

u选的时候:u的儿子必定不能选,所以dp[u][1]+=dp[v][0]   然后dp[u][1]+=w[u]表示加上u这个点

答案自然就是max(dp[rt][0],dp[rt][1])了

#include"cstdio"
#include"queue"
#include"cmath"
#include"stack"
#include"iostream"
#include"algorithm"
#include"cstring"
#include"queue"
#include"map"
#include"set"
#include"vector"
#include"bitset"
#define LL long long
#define ull unsigned long long
#define mems(a,b) memset(a,b,sizeof(a))
#define mdzz int mid=(L+R)>>1
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;

const int N = 6005;
const int M = 1e5+5;
const int MOD = 998244353;
const int INF = 0x3f3f3f3f;

int tot;
int first[N],w[N],deg[N];
int dp[N][2];

struct node{
    int e,next;
    node(){}
    node(int a,int b):e(a),next(b){}
}edge[M];

void init(){
    tot=0;
    mems(first,-1);
    mems(deg,0);
    mems(dp,0);
}

void addedge(int u,int v){
    edge[tot]=node(v,first[u]);
    first[u]=tot++;
}

void dfs(int u){
    dp[u][0]=0;
    dp[u][1]=w[u];
    for(int i=first[u];i!=-1;i=edge[i].next){
        int v=edge[i].e;
        dfs(v);
        dp[u][0]+=max(dp[v][1],dp[v][0]);
        dp[u][1]+=dp[v][0];
    }
}
int n;
int main(){
    //freopen("in.txt","r",stdin);
    while(~scanf("%d",&n)){
        init();
        for(int i=1;i<=n;i++) scanf("%d",&w[i]);
        int u,v;
        while(1){
            scanf("%d%d",&v,&u);
            if(!v&&!u) break;
            addedge(u,v);deg[v]++;
        }
        int rt;
        for(int i=1;i<=n;i++) if(!deg[i]){
            dfs(rt=i);
            break;
        }
        printf("%d\n",max(dp[rt][0],dp[rt][1]));
    }
    return 0;
}
View Code

相关文章:

  • 2022-01-04
  • 2022-12-23
  • 2022-12-23
  • 2021-11-05
  • 2021-12-14
  • 2021-05-21
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2021-08-27
  • 2021-11-19
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案