这两道题很类似,先说第一道题。定义dp[i][j]表示根结点为i时,用掉j个士兵得到的最大possible。
dp[i][j] = max(dp[i][j], dp[i][j-k] + dp[son[i]][k]);
递归的求出dp[son[i]][k]的值。最后结果就是dp[1][m];
用临界矩阵存图。
核心代码:
void dfs(int root) { int i, j, k, child, len; vis[root] = true; for(i = tree[root].bugs; i <= m; i++) { dp[root][i] = tree[root].p; } len = g[root].size(); for(i = 0; i < len; i++) { child = g[root][i]; if(!vis[child]) { dfs(child); for(j = m; j >= tree[root].bugs; j--) for(k = 1; k + j <= m; k++) dp[root][j+k] = max(dp[root][j+k], dp[root][j] + dp[child][k]); } } }
第二题跟第一题一样,不过它是以0为根结点,而0上没有权值。所以根为0时单独处理一下。转移方程跟上面一样:
核心代码:
void dfs(int r) { int i, j, k, len, c; vis[r] = true; for(i = 1; i <= m; i++) { dp[r][i] = p[r]; } if(r == 0) dp[r][0] = p[r]; len = g[r].size(); for(i = 0; i < len; i++) { c = g[r][i]; if(!vis[c]) { dfs(c); for(j = m; j >= (r == 0 ? 0 : 1); j --) { for(k = 1; k + j <= m; k++) { if(dp[c][k] != -1 && dp[r][j] != -1) { dp[r][j + k] = max(dp[r][j+k], dp[r][j] + dp[c][k]); } } } } } }