DP tree has a unique optimization is through recursive enumeration of the number of elements currently in force, seeking DP [i] [j] (i represents select subtree rooted has j elements selected maximum value )
(With siz array represents the total number of descendants of the current node)
1. hdu1561 (bare tree knapsack problem dependent)
Note siz arrays use, and when to reverse enumerate the number of nodes u point selection, just 01 backpack
Complexity seemingly O (n ^ 3), is actually about O (n ^ 2).
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int maxn = 250 ; vector<int> g[maxn]; int dp[maxn][maxn]; int val[maxn]; int siz[maxn]; int n,m; // DP [i] [j] represents the selected subtree rooted at i j elements selected have the maximum value of void DFS ( int U) { [u] = 1 ; dp[u][1] = val[u]; for(int i=0; i<g[u].size(); i++){ int v = g[u][i]; DFS (V); // where siz [u] is not included siz [v], and is the low efficiency of the process do give 2 ^ n with a backpack 01 for ( int I = siz [u]; I> = . 1 ; I -) { // here backpack like 01, to avoid this situation by the recursive point where this point is better for ( int J = . 1 ; J <= SIZ [V] && I + J <= m ; J ++) { // it is such as to avoid just said to take three points from v Release optimal dp [u] [i + j ] = max (dp [u] [i + j], dp [u] [I] + dp [V] [j]); // rear and from the front of the dp value obtained just take a wrong points better solution from the j } } [u] + = [c]; } } int main(){ while(scanf("%d%d",&n,&m)!=EOF){ if(n==0&&m==0) break; for(int i=0; i<=n; i++){ for(int j=0; j<=n; j++){ dp[i][j] = 0; } g[i].clear(); } int t; for(int i=1; i<=n; i++){ scanf("%d%d",&t,val+i); g[t].push_back(i); } m++; dfs(0); printf("%d\n", dp[0][m]); } }
2. codeforces 815C (tree dp)
The selected tree items may not need to have a parent-child relationship, but the use of coupons and about the relationship between father and son, so you can put dp increased more than one-dimensional array, indicating whether or not to use coupons.
Only you need to set the default value inf, then this initialization:
dp[u][0][0]=0;
dp[u][1][0]=c[u];
dp[u][1][1]=c[u]-d[u];
We can consider this element to zero at the time of enumeration.
#include <cstdio> #include <algorithm> #include <cstring> #include <vector> using namespace std; const int MAXN = 5005 ; int DP [MAXN] [MAXN] [ 2 ]; // DP [i] [j] denotes the subtree rooted at i j elements take the maximum Vector < int > G [MAXN ]; // again one-dimensional representation if i buy this root element, that is, do not use coupons int Val [MAXN], d [MAXN]; int SIZ [MAXN]; void dfs(int u){ [u] = 1 ; dp[u][1][1] = val[u]-d[u]; dp[u][1][0] = val[u]; dp[u][0][0] = 0; for(int i=0; i<g[u].size(); i++){ int v=g[u][i]; DFS (V); // where siz [u] is not included SIZ [V] for ( int I = siz [u]; I> = 0 ; I -) { // Here 0 to processing may not take for ( int J = 0 ; J <= SIZ [V]; J ++ ) { dp[u][i+j][0] = min(dp[u][i+j][0], dp[u][i][0]+dp[v][j][0]); dp[u][i+j][1] = min(dp[u][i+j][1], dp[u][i][1]+min(dp[v][j][0],dp[v][j][1])); } } [u] + = [c]; } } int main(){ int n,b; scanf("%d%d",&n,&b); scanf("%d%d",val+1,d+1); for(int i=2; i<=n; i++){ int t; scanf("%d%d%d",val+i,d+i,&t); g[t].push_back(i); } memset(dp,0x3f,sizeof(dp)); dfs(1); int ans=n; while(dp[1][ans][1]>b&&dp[1][ans][0]>b){ ans--; //printf("%d %d\n",dp[1][ans][1],dp[1][ans][0] ); } printf("%d\n", ans); }