HDU 4044 GeoDefense
树形DP,和背包差不多。dp[now][x]表示now这个节点的子树上,花费为x的时候,获得的最大防御能力(保证敌方HP<=0)
#include<cstdio> #include<cstring> #include<queue> #include<algorithm> using namespace std; const int maxn = 1000 + 10; int T, n, m; vector<int>tree[maxn]; struct kind { int price; int power; kind(int a, int b){ price = a; power = b; } }; vector<kind>v[maxn]; bool vis[maxn]; int dp[maxn][200 + 10]; int flag[200 + 10], tmp[200 + 10]; void init() { for (int i = 0; i <= n; i++) tree[i].clear(); for (int i = 0; i <= n; i++) v[i].clear(); memset(vis, 0, sizeof vis); memset(dp, -1, sizeof dp); } void read() { scanf("%d", &n); for (int i = 1; i <= n - 1; i++) { int u, v; scanf("%d%d", &u, &v); tree[u].push_back(v); tree[v].push_back(u); } scanf("%d", &m); for (int i = 1; i <= n; i++) { int ki; scanf("%d", &ki); while (ki--) { int pricei, poweri; scanf("%d%d", &pricei, &poweri); kind k(pricei, poweri); v[i].push_back(k); } } } void dfs(int now) { bool fail = 1; for (int i = 0; i<tree[now].size(); i++) if (!vis[tree[now][i]]) fail = 0; if (fail) { for (int i = 0; i<v[now].size(); i++) dp[now][v[now][i].price] = max(dp[now][v[now][i].price], v[now][i].power); return; } bool d[maxn]; memset(d, 0, sizeof d); for (int i = 0; i<tree[now].size(); i++) { if (vis[tree[now][i]]) continue; int id = tree[now][i]; vis[id] = 1; dfs(id); d[i] = 1; } memset(flag, -1, sizeof flag); bool first = 1; for (int i = 0; i<tree[now].size(); i++) { if (!d[i]) continue; int id = tree[now][i]; if (first) { first = 0; for (int j = 0; j <= m; j++) flag[j] = dp[id][j]; } else { memset(tmp, -1, sizeof tmp); for (int j = 0; j <= m; j++) for (int k = 0; k <= m; k++) if (dp[id][j] != -1 && flag[k] != -1 && j + k <= m) tmp[j + k] = max(tmp[j + k], min(dp[id][j], flag[k])); for (int j = 0; j <= m; j++) flag[j] = tmp[j]; } } for (int i = 0; i<v[now].size(); i++) for (int j = m; j >= v[now][i].price; j--) if (flag[j - v[now][i].price] != -1) dp[now][j] = max(dp[now][j], flag[j - v[now][i].price] + v[now][i].power); for (int i = 0; i <= m; i++) dp[now][i] = max(dp[now][i], flag[i]); for (int i = 0; i<v[now].size(); i++) dp[now][v[now][i].price] = max(dp[now][v[now][i].price], v[now][i].power); } void work() { vis[1] = 1; dfs(1); int ans = 0; for (int i = 0; i <= m; i++) ans = max(ans, dp[1][i]); printf("%d\n", ans); } int main() { scanf("%d", &T); while (T--) { init(); read(); work(); } return 0; }