洛谷 P1352 没有上司的舞会(树形DP)
这是一道终极经典的树形DP的例题。
树形dp就是将DP的数据放到了一棵树上。每个父节点与其子节点的值有关。推出如何建树和递推公式即可。
f[i][j].(j=1/0)i表示这是谁,j为1时表示来,0时表示不来。这个式子表示i来或不来时的最大快乐值。
设k为他的下属。
则f[i][1]+=f[k][0],f[i][0]+=max(f[k][0],f[k][1]).
即当i来时,j肯定不能来。则加上k不能来时的最大快乐值。
当i不来时,j来不来都有可能。则加上j来和不来中的最大值。
AC代码如下:
#include<cstdio> #include<algorithm> #include<vector> using namespace std; typedef long long ll; int n,h[6005],v[6005],f[6005][2]; vector<int> son[6005]; void dp(int x){ f[x][0]=0; f[x][1]=h[x]; for(int i=0;i<son[x].size();i++){ int y=son[x][i]; dp(y); f[x][0]+=max(f[y][0],f[y][1]); f[x][1]+=f[y][0]; } } int main(){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d",&h[i]); } for(int i=0;i<n-1;i++){ int x,y; scanf("%d%d",&x,&y); son[y-1].push_back(x-1); v[x-1]=1; } int root; for(int i=0;i<n;i++) if(!v[i]){ root=i; break; } dp(root); printf("%d\n",max(f[root][0],f[root][1])); return 0; }

浙公网安备 33010602011771号