hdu 1011 树形dp+背包
题意:有n个房间结构可看成一棵树,有m个士兵,从1号房间开始让士兵向相邻的房间出发,每个房间有一定的敌人,每个士兵可以对抗20个敌人,士兵在某个房间对抗敌人使无法走开,同时有一个价值,问你花费这m个士兵可以得到的最大价值是多少
链接:点我
分析:树形dp,对于点u,dp[u][j]表示以u为根的树消耗j个士兵得到的最大值,dp[i][j]=max(dp[i][j],dp[i][j-k]+dp[son][k]+val[u])
注意是无向图,vis位置不能随便放,且注意dp不能直接+val,因为这样根节点就加不到val了
虽然方程很快就想出来了,真写起来wa点还是很多的
第二次做
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 #include<map> 8 using namespace std; 9 #define MOD 1000000007 10 const int INF=0x3f3f3f3f; 11 const double eps=1e-5; 12 typedef long long ll; 13 #define cl(a) memset(a,0,sizeof(a)) 14 #define ts printf("*****\n"); 15 const int MAXN=601; 16 int n,m,tt; 17 int aa[MAXN]; 18 int tot,head[MAXN],dp[MAXN][MAXN],in[MAXN]; 19 int bug[MAXN],val[MAXN],vis[MAXN]; 20 struct Edge 21 { 22 int to,next; 23 }edge[MAXN<<2]; 24 void addedge(int u,int v) 25 { 26 edge[tot].to=v; 27 edge[tot].next=head[u]; 28 head[u]=tot++; 29 } 30 void dfs(int u) 31 { 32 vis[u]=1; 33 int num=(bug[u]+19)/20; 34 for(int i=num;i<=m;i++) dp[u][i]=val[u]; 35 for(int i=head[u];i!=-1;i=edge[i].next) 36 { 37 int v=edge[i].to; 38 if(vis[v]) continue; 39 dfs(v); 40 for(int j=m;j>=num;j--) 41 { 42 for(int k=1;j-k>=num;k++) //派k人攻打其他地方 43 { 44 dp[u][j]=max(dp[u][j],dp[u][j-k]+dp[v][k]); 45 } 46 } 47 } 48 } 49 void init() 50 { 51 tot=0; 52 memset(head,-1,sizeof(head)); 53 cl(dp); 54 cl(vis); 55 } 56 int main() 57 { 58 int i,j,k; 59 #ifndef ONLINE_JUDGE 60 freopen("1.in","r",stdin); 61 #endif 62 while(scanf("%d%d",&n,&m)!=EOF) 63 { 64 if(n==-1&&m==-1) break; 65 init(); 66 for(i=1;i<=n;i++) 67 { 68 scanf("%d%d",&bug[i],&val[i]); 69 } 70 int u,v; 71 for(i=1;i<=n-1;i++) 72 { 73 scanf("%d%d",&u,&v); 74 addedge(u,v); 75 addedge(v,u); 76 } 77 if(m==0) 78 { 79 printf("0\n"); 80 continue; 81 } 82 dfs(1); 83 printf("%d\n",dp[1][m]); 84 } 85 }