zoj3626 Treasure Hunt I 树上DP

点击打开链接

题意:

给你一颗树,然后每个点有一个价值,每个边有一个代价,然后问你,从k点出发,花费最多m/2的代价,能够取得最多的价值是多少。

思路:

树上背包问题,dp[i][j]表示从i点出发,花费j的代价所能取得的最大价值是多少。
转移方程为 dp[i][j]=max(dp[i][j],dp[i][m-k-t[i][v]]+dp[v][k])  就是以u为父节点 走不走v这个点   从不同的费用转移过来


代码:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 typedef long long ll;
 7 
 8 const int maxn = 5e4+10;
 9 int n,val[105],k,m;
10 int dp[105][205],vis[105];
11 vector<pair<int,int> > G[105];
12 
13 void dfs(int u){
14     vis[u] = 1;
15     dp[u][0] = val[u];
16     for(int i=0; i<G[u].size(); i++){
17         int v = G[u][i].first, w = G[u][i].second;
18         if(vis[v]==0){    
19             dfs(v);
20             for(int j=m; j>=0; j--)
21                 for(int k=0; k<=j-w; k++)
22                     dp[u][j] = max(dp[u][j],dp[u][j-k-w]+dp[v][k]);
23         }
24     }
25 }
26 
27 int main(){
28     while(cin >> n){
29         memset(dp,0,sizeof(dp));
30         memset(vis,0,sizeof(vis));
31         for(int i=1;i<=n;i++)
32             G[i].clear();
33         for(int i=1; i<=n; i++){
34             cin >> val[i];
35             dp[i][0] = val[i];
36         }
37         for(int i=1; i<=n-1; i++){
38             int a,b,c; cin>>a>>b>>c;
39             G[a].push_back(make_pair(b,c));
40             G[b].push_back(make_pair(a,c));
41         }
42         cin >> k >> m;
43         m = m/2;
44         dfs(k);
45 
46         int ans = 0;
47         for(int i=0; i<=m; i++)
48             if(dp[k][i] > ans)
49                 ans = max(ans,dp[k][i]);
50         cout << ans << endl;
51     }
52 }

 

posted @ 2017-02-23 19:39  _yxg123  阅读(79)  评论(0编辑  收藏  举报