标签:
n个洞穴,m个骑兵
每个骑兵最多可以打赢20个虫子
每个洞穴中打架的骑兵不能到其他洞穴
每个洞穴有一定的概率存在brain
合理支配m个骑兵,获取最大收益(最大抓住brain的概率)
// hdu 1011 // tree dp // Feb.16 2015 #include <cstdio> #include <vector> #include <cstring> #include <cmath> #include <algorithm> #define MAXN 111 std::vector<int> tunnel[MAXN]; int n, m, dp[MAXN][MAXN], bugs[MAXN], possi[MAXN]; // dp(num)(i) is the total possibility assign (i) Troopers to capture // the tree whose root is (num) bool vis[MAXN]; void dfs(int num) { vis[num] = true; // for the cave numbered (num) // at least ( ceil(bugs[num]/20) ) Troopers are need for(int i = bugs[num]; i <= m; ++i) dp[num][i] = possi[num]; for(int i = 0; i < tunnel[num].size(); ++i){ if(vis[ tunnel[num][i] ] == true) continue; dfs( tunnel[num][i] ); // 对于一个根节点编号为num的子树 // j为num节点的指派Trooper数量 // k为除num节点以外其他节点上Trooper数量 for(int j = m; j >= bugs[num]; --j) for(int k = 1; k + bugs[num] <= j; ++k) dp[num][j] = std::max( dp[num][bugs[num]], dp[num][bugs[num]] + dp[ tunnel[num][i] ][k] ); } } int main(int argc, char const *argv[]) { // freopen("in", "r", stdin); while(scanf("%d%d", &n, &m)){ if(n == -1 && m == -1) return 0; memset(dp, 0, sizeof(dp)); memset(vis, false, sizeof(vis)); for(int i = 1; i <= n; ++i){ scanf("%d%d", bugs+i, possi + i); bugs[i] = ceil(double(bugs[i])/20); // transform how many bugs into how many Troopers can defeat bugs in the cave tunnel[i].clear(); } for(int i = 1, a, b; i < n; ++i){ scanf("%d%d", &a, &b); tunnel[a].push_back(b); tunnel[b].push_back(a); } // if there is 0 bug in a cave // we still need at least 1 Trooper to capture this cave if( m == 0 ){ printf("0\n"); continue; } dfs(1); // the aim status printf("%d\n", dp[1][m]); } return 0; }
标签:
原文地址:http://www.cnblogs.com/takeoffyoung/p/4293647.html