因为苹果可能在不同的子树中,所以,很容易想到设状态dp_back[i][j]为以i点为树根走j步并回到i点的最大苹果数与dp_to[i][j]不回到i点的两个状态。

于是,转移方程就很明显了。只是注意要减去一来一回,或者不回的边。树形DP里套背包。

但这题远比这复杂,个人认为。因为在实现上细节太多。

实现代码1:

 #include <iostream>
#include <cstdio>
#include <vector>
using namespace std; const int MAX=;
vector<int>G[MAX];
int num[MAX],dp_back[MAX][MAX*],dp_to[MAX][MAX*];
int tback[MAX*],tto[MAX*];
int n,s; void init(){
for(int i=;i<=n;i++)
G[i].clear();
memset(dp_back,,sizeof(dp_back));
memset(dp_to,,sizeof(dp_to));
} void dfs(int u,int f){
int size=G[u].size();
for(int i=;i<size;i++){
int v=G[u][i];
if(v!=f){
dfs(v,u);
for(int p=;p<=s;p++){
tback[p]=dp_back[u][p];
tto[p]=dp_to[u][p];
for(int k=;k<=p;k++){
if(p-k->=){
tback[p]=max(tback[p],dp_back[u][p-k-]+dp_back[v][k]+num[v]);
}
if(p-k->=){
tto[p]=max(tto[p],dp_back[u][p-k-]+dp_to[v][k]+num[v]);
}
if(p-k->=){
tto[p]=max(tto[p],dp_to[u][p-k-]+dp_back[v][k]+num[v]);
}
}
}
for(int j=;j<=s;j++){
dp_back[u][j]=tback[j];
dp_to[u][j]=tto[j];
}
}
}
} int main(){
int u,v;
while(scanf("%d%d",&n,&s)!=EOF){
init();
for(int i=;i<=n;i++)
scanf("%d",&num[i]);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(,);
int ans=max(dp_to[][s],dp_back[][s]);
ans+=num[];
printf("%d\n",ans);
}
return ;
}

这是我WA了N久后看了别人的改过来的,每次在DP时才把根节点的值加上。说不清为什么,但是对了。

另一个是我原本WA的代码,可以把OJ的讨论板所有数据都过了,但依然WA,后来研究了好久,发现自己代码上的一个问题,那就是当最大步数超过边数的两倍时,就会出现问

题,于是,我只好投机一点,最后扫描一次结果值来获得正确值了。

 #include <iostream>
#include <cstdio>
#include <vector>
using namespace std; const int MAX=;
vector<int>G[MAX];
int num[MAX],dp_back[MAX][MAX*],dp_to[MAX][MAX*];
int tback[MAX*],tto[MAX*];
int n,s; void init(){
for(int i=;i<=n;i++)
G[i].clear();
memset(dp_back,,sizeof(dp_back));
memset(dp_to,,sizeof(dp_to));
} void dfs(int u,int f){
int size=G[u].size();
dp_back[u][]=num[u];
dp_to[u][]=num[u];
for(int i=;i<size;i++){
int v=G[u][i];
if(v!=f){
dfs(v,u);
for(int p=;p<=s;p++){
tback[p]=dp_back[u][p];
tto[p]=dp_to[u][p];
for(int k=;k<=p;k++){
if(p-k->=){
tback[p]=max(tback[p],dp_back[u][p-k-]+dp_back[v][k]);
}
if(p-k->=){
tto[p]=max(tto[p],dp_back[u][p-k-]+dp_to[v][k]);
}
if(p-k->=){
tto[p]=max(tto[p],dp_to[u][p-k-]+dp_back[v][k]);
}
}
}
for(int j=;j<=s;j++){
dp_back[u][j]=tback[j];
dp_to[u][j]=tto[j];
}
}
}
} int main(){
int u,v;
while(scanf("%d%d",&n,&s)!=EOF){
init();
for(int i=;i<=n;i++)
scanf("%d",&num[i]);
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(,);
// int ans=max(dp_to[1][s],dp_back[1][s]);
// ans+=num[1];
int ans=;
for(int i=;i<=s;i++)
ans=max(ans,max(dp_back[][i],dp_to[][i]));
printf("%d\n",ans);
}
return ;
}

两个代码除了初始化的位置不一样,其他都是一样的。但我感觉代码2更符合本来的转移方程,你看一下初始化的位置就明白。但最终问题时,不能处理好,那就是当最大步数超过边数的两倍时问题,因为我在初始化时就认为这是一种不可能的情况了。。。

所以,请路过大牛给指点,以去掉最后的扫描一次得到结果。。。

POJ 2486的更多相关文章

  1. 【POJ 2486】 Apple Tree (树形DP)

    Apple Tree Description Wshxzt is a lovely girl. She likes apple very much. One day HX takes her to a ...

  2. Apple Tree POJ - 2486 (树形dp)

    题目链接: D - 树形dp  POJ - 2486 题目大意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值 学习网址:https://blog.c ...

  3. Apple Tree POJ - 2486

    Apple Tree POJ - 2486 题目大意:一棵点带权有根树,根节点为1.从根节点出发,走k步,求能收集的最大权值和. 树形dp.复杂度可能是O(玄学),不会超过$O(nk^2)$.(反正这 ...

  4. 【POJ 2486】 Apple Tree(树型dp)

    [POJ 2486] Apple Tree(树型dp) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 8981   Acce ...

  5. E - Apple Tree POJ - 2486

    E - Apple Tree POJ - 2486 Wshxzt is a lovely girl. She likes apple very much. One day HX takes her t ...

  6. poj 2486( 树形dp)

    题目链接:http://poj.org/problem?id=2486 思路:经典的树形dp,想了好久的状态转移.dp[i][j][0]表示从i出发走了j步最后没有回到i,dp[i][j][1]表示从 ...

  7. POJ 2486 Apple Tree(树形dp)

    http://poj.org/problem?id=2486 题意: 有n个点,每个点有一个权值,从1出发,走k步,最多能获得多少权值.(每个点只能获得一次) 思路: 从1点开始,往下dfs,对于每个 ...

  8. POJ 2486 Apple Tree

    好抽象的树形DP......... Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6411 Accepte ...

  9. poj 2486 Apple Tree(树形DP 状态方程有点难想)

    Apple Tree Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9808   Accepted: 3260 Descri ...

  10. POJ 2486 Apple Tree(树形DP)

    题目链接 树形DP很弱啊,开始看题,觉得貌似挺简单的,然后发现貌似还可以往回走...然后就不知道怎么做了... 看看了题解http://www.cnblogs.com/wuyiqi/archive/2 ...

随机推荐

  1. linux 编译安装TRMPdump(libRTMP)

    需要编译libRTMP,首先需要安装配置编译环境.网上能够找到的资料多是在Windows环境编译.这里介绍一下在Linux系统中编译安装libRTMP,一来给后来者一个参考,二来也给自己做一个备忘录. ...

  2. 75.培训管理-培训信息发布 Extjs 页面

    1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8&quo ...

  3. ul和li里面的list-style

    对ul   list-type  只是设置ul的样式对li    list-type 是对li的综合样式设定  语法是 li-style:list-style-type/list-style-imag ...

  4. springboot+webmagic实现java爬虫jdbc及mysql

    前段时间需要爬取网页上的信息,自己对于爬虫没有任何了解,就了解了一下webmagic,写了个简单的爬虫. 一.首先介绍一下webmagic: webmagic采用完全模块化的设计,功能覆盖整个爬虫的生 ...

  5. Java冒泡,快速,插入,选择排序^_^+二分算法查找

    这段时间在学Java,期间学到了一些排序和查找方法.特此写来和大家交流,也方便自己的日后查看与复习. 1.下边是Java的主类: public class Get { public static vo ...

  6. 华为 荣耀 等手机解锁BootLoader

    下载工具按提示操作即可 链接:https://pan.baidu.com/s/1qZezd1q 密码:8pad 备用链接:https://pan.baidu.com/s/1nwv0heD

  7. poj3669 广搜

    //好久没刷题了,生疏了. 题意分析: 题意理解为在一个二维的正向坐标轴上,一个点(流星)连同它的上下左右的四个点会在某一个时刻被破坏.一个人在原点,问她到达安全区的最小时间是多少. 代码思路: 从原 ...

  8. dubbo之直连提供者

    在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,A 接口配置点对点,不影响 B 接口从注册中心获 ...

  9. andorid 查看OpenCv Mat的Debug信息

    在进行Android调试时,不能再Console显示Debug信息,只能在LogCat上显示,显示信息如下图: 代码段: public void printMat2Txt(Mat ElemM, Str ...

  10. Linux 之secureCRT连接SSH

    1.登陆linux系统,打开终端命令.输入 rpm -qa |grep ssh 查找当前系统是否已经安装. 2.如果没有安装SSH软件包,可以通过yum  或rpm安装包进行安装. .3.安装好了之后 ...