http://acm.hdu.edu.cn/showproblem.php?pid=4276
树形dp 比赛时时间不够了没写
基本思路:
先求是否能到达 如果能到达求每个子树在一定时间下的最优解
ans[i][j] 表示的是 以 i 的父节点为根的子树 还有 j 时间时的最优解
注意的是 到n的路径必须走无需返回 其他的可以走且需要返回
还有一条路所花时间可能是 0 (这里让我wa了N久呀)
代码及其注释:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <algorithm>
#define LL long long
using namespace std;
const int N=103;
const int INF=0x5fffffff;
int a[N];//财宝
int ans[N][N*5];//如上所诉
//邻接表
int head[N];
struct node
{
int j,next;
int d;
}side[N*2];
int I;
int n;
int limit[N];//为-1 表示没有限制 否则表示是到出口的路径 必须走 而且到 i 的时候时间最少为limit[i]
void build(int i,int j,int d)
{
side[I].j=j;
side[I].d=d;
side[I].next=head[i];
head[i]=I++;
}
void dfs(int x,int pre)//求出limit 并且去掉多余边
{
int f=0;
for(int t=head[x];t!=0;f=t,t=side[t].next)
{
int l=side[t].j;
if(l!=pre)
{
dfs(l,x);
if(limit[l]!=-1)
limit[x]=limit[l]+side[t].d;
}else
{
if(f==0)
head[x]=side[t].next;
else
side[f].next=side[t].next;
}
}
if(x==n)
limit[x]=0;
}
int dp(int x,int m)
{
int l=side[x].j;
if(ans[l][m]!=-1)//表
return ans[l][m];
if(limit[l]!=-1&&side[x].d+limit[l]>m)//此路必走 但时间不够则属于非法的走法 答案负无穷
{
ans[l][m]=-INF;return ans[l][m];
}
ans[l][m]=0;
if(l==0)//没有节点
{return ans[l][m];}
if(limit[l]==-1)//可以直接到兄弟节点 此节点不走
ans[l][m]=dp(side[x].next,m);
if(limit[l]==-1)
{
int temp=m-side[x].d*2;//往返
for(int i=0;i<=temp;++i)
{
ans[l][m]=max(ans[l][m],a[l]+dp(head[l],i)+dp(side[x].next,temp-i));
}
}else
{
int temp=m-side[x].d;//无需往返 时间至少为limit[l]
for(int i=limit[l];i<=temp;++i)
{
ans[l][m]=max(ans[l][m],a[l]+dp(head[l],i)+dp(side[x].next,temp-i));
}
}
return ans[l][m];
}
int main()
{
//freopen("data.txt","r",stdin);
int m;
while(scanf("%d %d",&n,&m)!=EOF)
{
memset(head,0,sizeof(head));
side[0].j=0;
I=1;
for(int i=1;i<n;++i)
{
int l,r,d;
scanf("%d %d %d",&l,&r,&d);
build(l,r,d);
build(r,l,d);
}
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
memset(limit,-1,sizeof(limit));
dfs(1,-1);
if(limit[1]>m)
{
printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
continue;
}
memset(ans,-1,sizeof(ans));
printf("%d\n", a[1]+dp(head[1],m));//第一个节点无需时间
}
return 0;
}
浙公网安备 33010602011771号