博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
POJ 2486
阅读量:4707 次
发布时间:2019-06-10

本文共 3201 字,大约阅读时间需要 10 分钟。

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

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

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

 

实现代码1:

1 #include 
2 #include
3 #include
4 using namespace std; 5 6 const int MAX=105; 7 vector
G[MAX]; 8 int num[MAX],dp_back[MAX][MAX*2],dp_to[MAX][MAX*2]; 9 int tback[MAX*2],tto[MAX*2];10 int n,s;11 12 void init(){13 for(int i=1;i<=n;i++)14 G[i].clear();15 memset(dp_back,0,sizeof(dp_back));16 memset(dp_to,0,sizeof(dp_to));17 }18 19 void dfs(int u,int f){20 int size=G[u].size();21 for(int i=0;i
=0){30 tback[p]=max(tback[p],dp_back[u][p-k-2]+dp_back[v][k]+num[v]);31 }32 if(p-k-1>=0){33 tto[p]=max(tto[p],dp_back[u][p-k-1]+dp_to[v][k]+num[v]);34 }35 if(p-k-2>=0){36 tto[p]=max(tto[p],dp_to[u][p-k-2]+dp_back[v][k]+num[v]);37 }38 }39 }40 for(int j=0;j<=s;j++){41 dp_back[u][j]=tback[j];42 dp_to[u][j]=tto[j];43 }44 }45 }46 }47 48 int main(){49 int u,v;50 while(scanf("%d%d",&n,&s)!=EOF){51 init();52 for(int i=1;i<=n;i++)53 scanf("%d",&num[i]);54 for(int i=1;i
View Code

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

 

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

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

1 #include 
2 #include
3 #include
4 using namespace std; 5 6 const int MAX=105; 7 vector
G[MAX]; 8 int num[MAX],dp_back[MAX][MAX*2],dp_to[MAX][MAX*2]; 9 int tback[MAX*2],tto[MAX*2];10 int n,s;11 12 void init(){13 for(int i=1;i<=n;i++)14 G[i].clear();15 memset(dp_back,0,sizeof(dp_back));16 memset(dp_to,0,sizeof(dp_to));17 }18 19 void dfs(int u,int f){20 int size=G[u].size();21 dp_back[u][0]=num[u];22 dp_to[u][0]=num[u];23 for(int i=0;i
=0){32 tback[p]=max(tback[p],dp_back[u][p-k-2]+dp_back[v][k]);33 }34 if(p-k-1>=0){35 tto[p]=max(tto[p],dp_back[u][p-k-1]+dp_to[v][k]);36 }37 if(p-k-2>=0){38 tto[p]=max(tto[p],dp_to[u][p-k-2]+dp_back[v][k]);39 }40 }41 }42 for(int j=0;j<=s;j++){43 dp_back[u][j]=tback[j];44 dp_to[u][j]=tto[j];45 }46 }47 }48 }49 50 int main(){51 int u,v;52 while(scanf("%d%d",&n,&s)!=EOF){53 init();54 for(int i=1;i<=n;i++)55 scanf("%d",&num[i]);56 for(int i=1;i
View Code

 

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

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

转载于:https://www.cnblogs.com/jie-dcai/p/3801658.html

你可能感兴趣的文章
中国城市json
查看>>
android下载手动下载Android SDK
查看>>
C++学习:任意合法状态下汉诺塔的移动(原创)
查看>>
leetcode133 - Clone Graph - medium
查看>>
一点小基础
查看>>
UNET学习笔记2 - 高级API(HLAPI)
查看>>
"ORA-00942: 表或视图不存在 "的原因和解决方法[转]
查看>>
Oauth支持的5类 grant_type 及说明
查看>>
C#中用DateTime的ParseExact方法解析日期时间(excel中使用系统默认的日期格式)
查看>>
W3100SM-S 短信猫代码发送 上
查看>>
Linux IO模式及 select、poll、epoll详解
查看>>
Log4j知识汇总
查看>>
python生成.exe文件
查看>>
PHP面向对象(OOP)----分页类
查看>>
监听SD卡状态
查看>>
vs2017 EFCore 迁移数据库命令
查看>>
serialVersionUID的作用
查看>>
liunx trac 插件使用之GanttCalendarPlugin
查看>>
(14)嵌入式软件开发工程师技能要求总结
查看>>
[hackerrank]Closest Number
查看>>