HDU_1011 Starship Troopers && HDU_1561 The more, The Better (树型dp)

  这两道题很类似,先说第一道题。定义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]);
                    }
                }
            }
        }
    }
}
posted @ 2012-01-06 11:50  AC_Von  阅读(237)  评论(0编辑  收藏  举报