您的位置:首页 > 其它

ZOJ-3626 Treasure Hunt I 树形DP

2014-08-29 15:13 357 查看
很久很久以前有一个吸血鬼,每m天就会出现一次,把不在自己村子呆着的冒险家吃掉。有n个村子,n-1条道路,每个村子都有一定数量的财富,默认探险家刚一到达一个村子就能获得财富,给出探险家的出生的村子和多少天后吸血鬼出现。

要求在吸血鬼出现之前赶回自己的村子,其实就是求一棵以k为根的各点权值之和最大且各边权加起来<=m/2的子树。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <queue>
#include <ctime>
#include <vector>
#include <algorithm>
#define LL __int64
#define inf 1<<29
using namespace std;
struct Edge
{
int v,next;
int len;
}edge[1000];
int num;
int head[1000];
void addedge(int u,int v,int len)
{
edge[num].v=v;
edge[num].len=len;
edge[num].next=head[u];
head[u]=num++;
edge[num].v=u;
edge[num].len=len;
edge[num].next=head[v];
head[v]=num++;
}
int a[222];
int dp[222][222];
int n,m,k;
void dfs(int root,int father,int d)
{
for(int i=head[root];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
int len=edge[i].len;
if(v==father)
{
continue;
}
dfs(v,root,d-len);
for(int j=d;j>=0;j--)
{
for(int k=0;k+len<=j;k++)
{
if(dp[v][k]!=0&&dp[root][j-k-len]!=0)
{
dp[root][j]=max(dp[root][j],dp[root][j-k-len]+dp[v][k]);
}
}
}
}
}
int main()
{
int u,v,len;
while(scanf("%d",&n)!=EOF)
{
memset(dp,0,sizeof(dp));
memset(head,-1,sizeof(head));
num=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
dp[i][0]=a[i];
}
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&len);
addedge(u,v,len);
}
scanf("%d%d",&k,&m);
m/=2;
dp[k][0]=a[k];
dfs(k,-1,m);
int ans=-1;
for(int i=0;i<=m;i++)
{
if(dp[k][i]>ans)
{
ans=dp[k][i];
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: