题意:
给你一颗树,然后每个点有一个价值,每个边有一个代价,然后问你,从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 }