您的位置:首页 > 其它

hdu 4276(树形dp)

2014-05-04 22:40 357 查看
题意:带权树上有起点终点每个点上有宝藏,一个人只有T分钟要从起点到重点,问你最多能收集多少宝藏。

思路:树形dp,首先判断能不能走到终点,然后把路径上的边权变为0时间减去所有边权。dp[v][j]表示从v出发回到v话费j分钟最多能收集到的宝藏。

dp[v][j] = max(dp[v][j], dp[x][k] + dp[v][j-k-2*val]);

被G++卡了好长时间,换成c++就过了。

代码如下:

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <set>
#include <iostream>
#include <queue>
#include <map>
#include <math.h>
#include <string>
#define MP(a, b) make_pair(a, b)
#define PB(a) push_back(a)
using namespace std;

const int LEN = 101;
typedef pair<int, int> pii;
int n, m, dp[LEN][LEN*5], vex[LEN], tans;
vector<pii> Map[LEN];

bool initdfs(int v, int fa){
if(v == n-1) return true;
for(int i=0; i<Map[v].size(); i++){
int x = Map[v][i].first;
if(x != fa){
if(initdfs(x, v)){
tans += Map[v][i].second;
Map[v][i].second = 0;
return true;
}
}
}
return false;
}

void dfs(int v, int fa){
for(int i=0; i<Map[v].size(); i++){
int x = Map[v][i].first, val = Map[v][i].second;
if(x != fa){
dfs(x, v);
for(int j=m; j>=0; j--){
for(int k=0; k<=j-2*val; k++){
dp[v][j] = max(dp[v][j], dp[x][k] + dp[v][j-k-2*val]);
}
}
}
}
for(int i=0; i<=m; i++) dp[v][i] += vex[v];
}

int main()
{
//    freopen("in.txt", "r", stdin);

int a, b, c;
while(scanf("%d%d", &n, &m)!=EOF){
for(int i=0; i<LEN; i++) Map[i].clear();
memset(dp, 0, sizeof dp);
tans = 0;
for(int i=0; i<n-1; i++){
scanf("%d%d%d", &a, &b, &c);
a--, b--;
Map[a].PB(MP(b, c));
Map[b].PB(MP(a, c));
}
for(int i=0; i<n; i++){
scanf("%d", &vex[i]);
}
initdfs(0, -1);
if(tans > m){
puts("Human beings die in pursuit of wealth, and birds die in pursuit of food!");
continue;
}
dfs(0, -1);
int ans = 0;
for(int i=0; i<=m-tans; i++){
ans = max(ans, dp[0][i]);
}
printf("%d\n", ans);
}
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: