HDU4044 GeoDefense(有点不一样的树上背包)

题目大概说一棵n个结点的树,每个结点都可以安装某一规格的一个塔,塔有价格和能量两个属性。现在一个敌人从1点出发但不知道他会怎么走,如果他经过一个结点的塔那他就会被塔攻击失去塔能量的HP,如果HP小于等于0敌人就挂了。任务就是在总花费不超过m的条件下在各个结点安装塔,求能预防的敌人的HP的最大值。

状态容易表示,dp[u][m]表示在结点u为根的子树中花费m能预防的最大的HP

转移显然又是树上背包了,不过略麻烦,想清楚的话还是能比较快地写完:

  • u子树从它孩子结点的子树的最小值中转移过来,因为各个孩子都必须选我用了一个临时数组存值转移完后更新回去
  • 这样处理完u的各个子树,再用一遍背包加上u结点本身能建的塔,就是dp[u]状态的值了

WA了一发,因为同一价格不同能量没考虑到。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define MAXN 1111
 6 struct Edge{
 7     int v,next;
 8 }edge[MAXN<<1];
 9 int NE,head[MAXN];
10 void addEdge(int u,int v){
11     edge[NE].v=v; edge[NE].next=head[u];
12     head[u]=NE++;
13 }
14 int m,mat[MAXN][222];
15 int d[MAXN][222],tmp[222];
16 void dp(int u,int fa){
17     d[u][0]=0;
18     bool first=1;
19     for(int i=head[u]; i!=-1; i=edge[i].next){
20         int v=edge[i].v;
21         if(v==fa) continue;
22         dp(v,u);
23         if(first){
24             first=0;
25             for(int j=0; j<=m; ++j) d[u][j]=d[v][j];
26             continue;
27         }
28         memset(tmp,-1,sizeof(tmp));
29         for(int j=0; j<=m; ++j){
30             for(int k=0; j+k<=m; ++k){
31                 tmp[j+k]=max(tmp[j+k],min(d[u][j],d[v][k]));
32             }
33         }
34         for(int j=0; j<=m; ++j) d[u][j]=tmp[j];
35     }
36     for(int i=m; i>=0; --i){
37         for(int j=0; j<=i; ++j){
38             if(d[u][i-j]==-1 || mat[u][j]==-1) continue;
39             d[u][i]=max(d[u][i],d[u][i-j]+mat[u][j]);
40         }
41     }
42 }
43 int main(){
44     int t,n,a,b,c;
45     scanf("%d",&t);
46     while(t--){
47         NE=0;
48         memset(head,-1,sizeof(head));
49         scanf("%d",&n);
50         for(int i=1; i<n; ++i){
51             scanf("%d%d",&a,&b);
52             addEdge(a,b); addEdge(b,a);
53         }
54         memset(mat,-1,sizeof(mat));
55         scanf("%d",&m);
56         for(int i=1; i<=n; ++i){
57             scanf("%d",&a);
58             while(a--){
59                 scanf("%d%d",&b,&c);
60                 mat[i][b]=max(mat[i][b],c);
61             }
62         }
63         memset(d,-1,sizeof(d));
64         dp(1,1);
65         int res=0;
66         for(int i=0; i<=m; ++i) res=max(res,d[1][i]);
67         printf("%d\n",res);
68     }
69     return 0;
70 }

 

posted @ 2016-03-30 10:33  WABoss  阅读(156)  评论(0编辑  收藏  举报