http://poj.org/problem?id=2486
树形DP 我一般都是先用邻接表保存树 然后用的都是子树和所有兄弟树的dp方法
自己感觉理解也行呀 但是没见有多少人用呢,也许自己有点另类
老是出错 思维能力还是不够 越来越感觉acm是在练一个人的思维了
题目大意:
给一个树 节点有一定数目的苹果
人在1(根点)最多走K步 问最多可以得到多少苹果
思路:
ans[i][j][0] 表示包括i在内所以其子节点和右边兄弟树 可以走j步 可以存在不回来的情况 的最佳答案
ans[i][j]][1] 这个必须都回来
代码及其注释:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<queue>
#include<cmath>
#include<stack>
#include<algorithm>
#define LL long long
using namespace std;
const int N=105;
const int MIN=-100000000;
struct node
{
struct tt *next;
}mem[N];
struct tt
{
int j;
struct tt *next;
};
bool had[N];
bool link[N][N];
int applenum[N];
int ans[N][N*2][2];
int a[3][3][3];
void build(int i,int j)
{
struct tt *t=new tt;
t->j=j;
t->next=mem[i].next;
mem[i].next=t;
}
void Dele(int n)
{
struct tt *t;
for(int i=1;i<=n;++i)
{//cout<<i<<endl;
while(mem[i].next!=NULL)
{//cout<<"iii"<<endl;
t=mem[i].next;
mem[i].next=t->next;
delete t;
}
}
}
int dp(struct tt *t,int k,int back)
{
if(t==NULL)//各种 无法走的情况
return 0;
if(k<0)
return 0;
if(back==1&&k<1)
return 0;
if(ans[t->j][k][back]!=-1)
return ans[t->j][k][back];
int itemp=0;
int w=0;
for(int i=0;i<=k;++i)
{
if(i>=1)
w=applenum[t->j];//要回去时 只有可以回去 才能加上本节点的苹果树
itemp=max(itemp,w+dp(mem[t->j].next,i-2,1)+dp(t->next,k-i-1,back));//给子树一部分 往兄弟传一部分 注意路径需要的步数减去
if(back==0)
{
w=applenum[t->j];//这是子树不用回来的 其他差不多
itemp=max(itemp,w+dp(mem[t->j].next,i-1,0)+dp(t->next,k-i-1,1));
}
}
ans[t->j][k][back]=itemp;
if(t->next!=NULL)
ans[t->j][k][back]=max(ans[t->j][k][back],dp(t->next,k,back));//如果不走此节点
return ans[t->j][k][back];
}
void dfs(int x,int n)
{
had[x]=true;
for(int i=1;i<=n;++i)
{
if(link[x][i]&&!had[i])
{
build(x,i);//建立单向树
dfs(i,n);
}
}
}
int main()
{
int n,k;
while(scanf("%d %d",&n,&k)!=EOF)
{
for(int i=1;i<=n;++i)
{
scanf("%d",&applenum[i]);
}
memset(link,false,sizeof(link));
for(int i=1;i<n;++i)
{
int x,y;
scanf("%d %d",&x,&y);
link[x][y]=link[y][x]=true;
}
if(n==1)
{
printf("%d\n",applenum[1]);
continue;
}
memset(had,false,sizeof(had));
dfs(1,n);
memset(ans,-1,sizeof(ans));
printf("%d\n",applenum[1]+dp(mem[1].next,k-1,0));
Dele(n);
}
}
浙公网安备 33010602011771号