POJ2486 Apple Tree 【树上背包】

一句话题意:一棵树,一共n个点,每个点上有一个权值,求从1出发,走k步,最多能遍历到的权值。可以往回走。

第一(二)道树上背包题,先是看了dalao的题解,改了一点就过样例了。然而....TLE??? 改了挺久发现由于多组数据且没有“0 0”的输入,如果不在读入的时候加“~”或“EOF”就会死循环,从而导致TLE。

状态设计:设f[i][j][0/1]为以i为根的子树上,走j步,能得到的最大权值(0/1的表示会在转移方程中描述) 考虑:(此处参考dalao@zubizakeli ,侵删qwq)每个节点在最终答案中的类型:1,不经过;2,经过但不返回;3,经过且返回 (返回的定义是最终的停止节点不位于该节点的子树中) 那么可以进行转移:

 

之后便是一些细节问题:给数组赋初值(从0开始!走0步),更新head数组。

实现还是比较简单的啦。

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 
 5 using namespace std;
 6 
 7 int n,k,tot;
 8 int w[300],head[300];
 9 int f[300][200][3]; 
10 struct node{
11     int to,next,val;
12 }edge[300];
13 
14 void add(int x,int y)
15 {
16     edge[++tot].to=y;
17     edge[tot].next=head[x];
18     head[x]=tot;
19 }
20 
21 void read(int &x)
22 {
23     x=0;
24     char ch=getchar();
25     bool flag=false;
26     while(ch<'0'||ch>'9') flag|=(ch=='-'),ch=getchar();
27     while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
28     x=flag ? -x : x;
29 }
30 
31 void TreeDp(int u,int fa)
32 {
33     for(int i=0;i<=k;i++) f[u][i][1]=w[u],f[u][i][0]=w[u];
34     for(int i=head[u];i;i=edge[i].next)
35     {
36         int v=edge[i].to;
37         if(v==fa) continue;
38         TreeDp(v,u);
39         for(int kk=k;kk>=0;kk--)
40         for(int j=0;j<=kk;j++)
41         {
42             if(kk>=j+2) f[u][kk][0]=max(f[u][kk][0],f[v][j][0]+f[u][kk-j-2][0]);
43             if(kk>=j+2) f[u][kk][1]=max(f[u][kk][1],f[v][j][0]+f[u][kk-j-2][1]);
44             if(kk>=j+1) f[u][kk][1]=max(f[u][kk][1],f[v][j][1]+f[u][kk-j-1][0]);
45         }
46     }
47 }
48 
49 void init()
50 {
51     memset(f,0,sizeof(f));
52     memset(head,0,sizeof(head));
53     tot=0;
54 } 
55 
56 int main()
57 {
58     while(scanf("%d%d",&n,&k)!=EOF)
59     {
60         for(int i=1;i<=n;i++) read(w[i]);
61         for(int i=1;i<=n-1;i++)
62         {
63             int x=0,y=0;
64             read(x),read(y);
65             add(x,y),add(y,x);
66         }
67         TreeDp(1,-1);
68         printf("%d\n",max(f[1][k][0],f[1][k][1]));
69         init();
70     }
71     return 0;
72 }
View Code

小结:分类讨论常常也是解题重要的突破口呐。

posted @ 2018-08-10 20:29  cellur925&Chemist  阅读(231)  评论(0编辑  收藏  举报