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这个点   从不同的费用转移过来


代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
typedef long long ll;

const int maxn = 5e4+10;
int n,val[105],k,m;
int dp[105][205],vis[105];
vector<pair<int,int> > G[105];

void dfs(int u){
	vis[u] = 1;
	dp[u][0] = val[u];
	for(int i=0; i<G[u].size(); i++){
		int v = G[u][i].first, w = G[u][i].second;
		if(vis[v]==0){	
			dfs(v);
			for(int j=m; j>=0; j--)
				for(int k=0; k<=j-w; k++)
					dp[u][j] = max(dp[u][j],dp[u][j-k-w]+dp[v][k]);
		}
	}
}

int main(){
	while(cin >> n){
		memset(dp,0,sizeof(dp));
		memset(vis,0,sizeof(vis));
		for(int i=1;i<=n;i++)
        	G[i].clear();
		for(int i=1; i<=n; i++){
			cin >> val[i];
			dp[i][0] = val[i];
		}
		for(int i=1; i<=n-1; i++){
			int a,b,c; cin>>a>>b>>c;
			G[a].push_back(make_pair(b,c));
			G[b].push_back(make_pair(a,c));
		}
		cin >> k >> m;
		m = m/2;
		dfs(k);

		int ans = 0;
		for(int i=0; i<=m; i++)
			if(dp[k][i] > ans)
				ans = max(ans,dp[k][i]);
		cout << ans << endl;
	}
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值