OJ題目:click here~~
題目分析:一棵樹,有n個結點 ,給每個結點的value 和 weight 。求容量為m的背包,能獲得的最大value。選擇了父結點才能選擇子結點。m = 0時 ,輸出0 , 即使有weight = 0 的結點,這是題目的一個trick。。
const int maxn = 102; int val[maxn]; int w[maxn]; vectorg[maxn]; int dp[maxn][maxn]; int n , m ; void dfs(int u , int father){ int v , i , j , k; for(i = w[u];i <= m;i++) dp[u][i] = val[u]; for(i = 0;i < g[u].size();i++){ v = g[u][i]; if(v == father) continue; dfs(v , u); for(j = m;j >= w[u];j--){ for(k = 1;k + j <= m;k++){ dp[u][j + k] = max(dp[u][j + k] , dp[v][k] + dp[u][j]); } } } } int main(){ int i , j , k ,a , b; //freopen("in.txt" , "r" , stdin); while(scanf("%d%d",&n,&m)){ if(n == -1 && m == -1) break; memset(dp , 0 , sizeof(dp)); for(i = 0 ;i <= n;i++) g[i].clear(); for(i = 1;i <= n;i++){ scanf("%d%d",&w[i] , &val[i]); w[i] = (w[i] + 19)/20;//計算每個結點需要的士兵數 } for(i = 1;i < n;i++){ scanf("%d%d", &a , &b); g[a].push_back(b); g[b].push_back(a); } if(m == 0) {puts("0") ; continue;}//沒有士兵時,不能獲得任何東西,即使有bug = 0的結點。 dfs(1 , -1); cout << dp[1][m] << endl; } }