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); } }