HDOJ 1011 Starship Troopers(树DP)
题意描述很纠结,前后WA了数十次……
AC后的理解:给一棵树,每个结点有2个值,bug和brain,要获取brain必先消灭bug,现从结点1出发,给你m个starship troopers,每个starship troopers能对付20个bug,问最多能得到多少brain。在攻克的过程中,对于途中经过的结点,如果该点bug不为0,则要留下一个starship troopers在此结点,否则不需留。对于叶子结点,即使bug为0,也要派starship troopers去收获brain。
data:
5 0
0 1 0 1 0 5 0 1 0 2 1 2 1 3 2 4 2 5
5 2
0 1 0 1 0 5 0 1 0 2 1 2 1 3 2 4 2 5
-1 -1
answer:0 9
View Code
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 110 int n,m,e; int bug[N],brain[N]; int first[N],next[N<<1],v[N<<1]; int dp[N][N]; void init() { e=0; memset(first,-1,sizeof(first)); } void add(int a,int b) { v[e]=b; next[e]=first[a]; first[a]=e++; } void dfs(int a,int fa) { dp[a][0]=0; for(int j=1;j<=m;j++) { dp[a][j]= j>=bug[a] ? brain[a] : 0; } int i,b; bool f=1; for(i=first[a];~i;i=next[i]) { b=v[i]; if(b==fa) continue; if(f) { if(bug[a]==0) dp[a][0]=brain[a]; f=0; } dfs(b,a); for(int j=m;j;j--) { for(int k=1;j-k>=bug[a];k++) { dp[a][j]=max(dp[a][j],dp[a][j-k]+dp[b][k]); } } } } int main() { int a,b; while(scanf("%d%d",&n,&m)) { if(n==-1 && m==-1) break; init(); for(int i=1;i<=n;i++) { scanf("%d%d",&bug[i],&brain[i]); bug[i]=(bug[i]+19)/20; } for(int i=1;i<n;i++) { scanf("%d%d",&a,&b); add(a,b); add(b,a); } if(m==0) { puts("0"); continue; } dfs(1,0); int ans=dp[1][m]; printf("%d\n",ans); } return 0; }