题意:在一个树状图中,每一个节点都有一个宝藏,给定起点标号为1,终点标号为n,求在特定时间内是否可以到达终点,并找出能得到的最大宝藏。
做法:参考大牛。在树的结构中任意两节点之间有且仅有一条通路。所以要得到额外宝藏时,必须折回到原路径才能走到终点。虽是如此,可是WA了许久,代码能力不足啊。
#include<stdio.h>
#include<string.h>
/*0的含义要记得
记得测试时,要拿1或者0规模的小数据,下面的错误就是在点为1 的时候出错的!!!!!*/
typedef struct
{
int u,v,t,next;
}line;
line e[210];
int path[105],val[105],get[105][255],dp[255],next[105];
int alt,dt,all,n;
int max(int a,int b)
{
return a>b?a:b;
}
void insert(int u,int v,int t)
{
e[all].u=u;
e[all].v=v;
e[all].t=t;
e[all].next=next[u];
next[u]=all++;
e[all].u=v;
e[all].v=u;
e[all].t=t;
e[all].next=next[v];
next[v]=all++;
}
int dfs(int u,int pre)
{
if(u==n)/*改成之前的if(v==n)
{
path[u]=path[v]=1;return e[x].t就错了。。。
}*/
{
path[u]=1;
return 0;
}
int v,x,ret;
for(x=next[u];x!=-1;x=e[x].next)
{
v=e[x].v;
if(v==pre)continue;
ret=dfs(v,u);
if(ret>=0)
{
path[u]=1;
return ret+e[x].t;
}
}
return -1;
}
void dfs2(int u,int pre)
{
int v,x,j,k;
get[u][0]=val[u];
for(x=next[u];x!=-1;x=e[x].next)
{
v=e[x].v;
if(v==pre)continue;
dfs2(v,u);
if(path[v])continue;
for(j=254;j>=0;j--)
for(k=0;k<=254;k++)//从小到大
if(k+e[x].t<=j&&get[u][j-e[x].t-k]!=-1)
get[u][j]=max(get[u][j],get[u][j-k-e[x].t]+get[v][k]);
}
}
int main()
{
int i,j,k;
while(scanf("%d%d",&n,&dt)!=EOF)
{
memset(next,-1,sizeof(next));
memset(dp,0,sizeof(dp));
memset(get,-1,sizeof(get));
memset(path,0,sizeof(path));
all=0;
for(i=1;i<n;i++)
{
int u,v,t;
scanf("%d%d%d",&u,&v,&t);
insert(u,v,t);
}
for(i=1;i<=n;i++)
scanf("%d",&val[i]);
alt=dfs(1,0);
if(alt>dt)
{
printf("Human beings die in pursuit of wealth, and birds die in pursuit of food!\n");
continue;
}
dfs2(1,0);
for(i=1;i<=n;i++)
if(path[i])
for(j=254;j>=0;j--)
for(k=0;k<=254;k++)
if(j-k>=0)
dp[j]=max(dp[j],dp[j-k]+get[i][k]);
printf("%d\n",dp[(dt-alt)>>1]);
}
return 0;
}