HDU 4276 The Ghost Blows Light
题目描述:
有一棵树,N~100,有时间T~500,起点是编号1,重点是给出的N,每个点有若干个宝,要求在时间内走到N出去,并且尽量拿到多的宝藏,输出最多宝藏数.
题解:
有个小技巧可以简化思维.一定要走的路先走一遍,并且不会反复走.这样先搞出,然后把路上的花费消除掉.之后就是正常的树形dp,加一维表示用了多少时间.画一个图就发现剩下的是树形依赖背包,想要用多少,画多少的时间.
重点:
简化思维.定状态时因为有一定要走的地方,所以不好弄,一定走的就先走,然后再贪心的定新的状态,一定要走的走.这样之后简化为一个树形依赖背包.而不是最初的定状态走到哪里.
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cmath>
#include <ctype.h>
#include <limits.h>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <queue>
#include <map>
#include <stack>
#include <set>
#include <bitset>
#define CLR(a) memset(a, 0, sizeof(a))
#define REP(i, a, b) for(int i = a;i < b;i++)
#define REP_D(i, a, b) for(int i = a;i <= b;i++)
typedef long long ll;
using namespace std;
const int maxn = 500 + 10;
int flag[maxn], dp[maxn][maxn], val[maxn], a, b, n, tot;
struct info
{
int to, t;
};
vector<info> G[maxn];
void dfs_flag(int u, int fa)//代码很简单,这是标记必走的路.
{
flag[u] = 0;
int tag = 0;
REP(i, 0, G[u].size())
{
int v = G[u][i].to;
if(v!=fa)
{
dfs_flag(v, u);
if(flag[v]!=0)
{
tag = 1;
}
}
}
if(u == b)
{
tag = 1;
}
flag[u] = tag;
}
void dfs(int u, int fa)//树形依赖背包,因为要根据fa到u的长度来定代价,所以再传下去的时候就进行减掉.其实这样写有点复杂了.因该分开写,先走一遍一定要走的路,然后把总时间减掉,之后再正常的dp就好了,因为一切的都是要回到原点的dp.
{
if(flag[u]==0 || u == b)
{
REP(i, 0, G[u].size())
{
int v = G[u][i].to, t = G[u][i].t;
if(v!=fa)
{
for(int j = t*2; j <= tot; j++)
{
if(dp[u][j-t*2]!=-1)
dp[v][j] = dp[u][j-t*2]+val[v];
else
dp[v][j] = -1;
}
for(int j = 0; j < t*2; j++)
{
dp[v][j] = -1;
}
dfs(v, u);
for(int j = 0; j <= tot; j++)
{
dp[u][j] = max(dp[u][j], dp[v][j]);
}
}
}
}
else
{
REP(i, 0, G[u].size())
{
int v = G[u][i].to, t = G[u][i].t;
if(v!=fa&&flag[v]==1)
{
for(int j = t; j <= tot; j++)
{
if(dp[u][j-t]!=-1)
dp[v][j] = dp[u][j-t]+val[v];
else
dp[v][j] = -1;
}
for(int j = 0; j < t; j++)
{
dp[v][j] = -1;
}
dfs(v, u);
for(int j = 0;j <= tot;j++)
dp[u][j] = dp[v][j];
}
else if(v!=fa&&flag[v]==0)
{
for(int j = t*2; j <= tot; j++)
{
if(dp[u][j-t*2]!=-1)
dp[v][j] = dp[u][j-t*2]+val[v];
else
dp[v][j] = -1;
}
for(int j = 0; j < t*2; j++)
{
dp[v][j] = -1;
}
dfs(v, u);
for(int j = 0; j <= tot; j++)
{
dp[u][j] = max(dp[u][j], dp[v][j]);
}
}
}
}
}
void solve()
{
dfs_flag(a, 0);
for(int j = 0; j <= tot; j++)
{
dp[a][j] = - 1;
}
dp[a][0] = val[a];
dfs(a, 0);
int ans = -1;
for(int i = 0;i <= tot;i++)
{
ans = max(ans, dp[a][i]);
}
if(ans == -1)
{
printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
}
else
{
printf("%d\n", ans);
}
}
int main()
{
// freopen("1Ain.txt", "r", stdin);
//freopen("1Aout.txt", "w", stdout);
while(scanf("%d%d", &n, &tot) != EOF)
{
REP_D(i, 1, n)
{
G[i].clear();
}
REP_D(i, 1, n - 1)
{
int x, y, len;
scanf("%d%d%d", &x, &y, &len);
info t;
t.to = y;
t.t = len;
G[x].push_back(t);
t.to = x;
G[y].push_back(t);
}
a = 1;
b = n;
REP_D(i, 1, n)
{
scanf("%d", &val[i]);
}
solve();
}
return 0;
}