GeoDefense
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=4044
题意:
给一棵n个节点的树,点1为敌方基地,叶子结点都为我方阵地。我们可以在每个结点安放炸弹,每点至多放一个,每个结点有k种炸弹可选,且每种炸弹有一个花费和一个攻击力(1点攻击力使敌人掉1点hp)。敌人的目的是我方阵地,任意路线都有可能,但规定只能往下跑。问当有m钱时,最坏情况下最多能打掉敌人多少
思路:
最坏情况下指的是敌人总是跑攻击力最小的那条路径。
dp[u][i]为u不选的时候花i元的最优解
w[u][j]对于u号点花费为j时的最大伤害
考虑一个叶子结点:dp[u][i]=w[u][i]
考虑一个非叶子结点不选时候:每一个儿子v加进来的时候,状态都分裂为dp[v][k]和dp[u][j-k]
对于每一个枚举的k来说,答案是min(dp[v][k],dp[u][j-k]) (代表最坏的情况)维护这个答案的最大值就是dp[u][j]
孩子考虑完了我们在考虑为当前这个节点分配多少钱才是最优的 (背包问题)
#include <iostream> #include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #define LL long long #define INF 0x3f3f3f3f #define ls nod<<1 #define rs (nod<<1)+1 const double eps = 1e-10; const int maxn = 1000 + 10; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; struct edge { int v,nxt; }e[maxn<<1]; int head[maxn]; int f[maxn][300],w[maxn][205]; int cnt; int n,m; inline void add_edge(int u,int v) { e[++cnt].v = v; e[cnt].nxt = head[u]; head[u] = cnt; } inline void dfs(int x,int fa) { int fl = 0; for (int i = head[x];~i;i = e[i].nxt) { int v = e[i].v; if (v == fa) continue; dfs(v,x); fl = 1; for (int j = m;j >= 0;j--) { int tmp = 0; for (int k = 0;k <= j;k++) { tmp = max(tmp,min(f[x][j-k],f[v][k])); } f[x][j] = tmp; } } if (fl == 0) { for (int j = 0;j <= m;j++) f[x][j] = w[x][j]; return ; } for (int j = m;j >= 0;j--) { for (int k = 0;k <= j;k++) f[x][j] = max(f[x][j],f[x][j-k]+w[x][k]); } } int main() { ios::sync_with_stdio(false); int T; cin >> T; while (T--) { cin >> n; cnt = 0; memset(head,-1, sizeof(head)); memset(w,0, sizeof(w)); memset(f,INF, sizeof(f)); for (int i = 1;i < n;i++) { int u,v; cin >> u >> v; add_edge(u,v); add_edge(v,u); } cin >> m; for (int i = 1;i <= n;i++) { int k; cin >> k; for (int j = 1;j <= k;j++) { int c,h; cin >> c >> h; w[i][c] = max(w[i][c],h); } for (int j = 0;j <= m;j++) w[i][j] = max(w[i][j],w[i][j-1]); } dfs(1,0); cout << f[1][m] << endl; } return 0; }