POJ 2486
因为苹果可能在不同的子树中,所以,很容易想到设状态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的更多相关文章
- 【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 ...
- Apple Tree POJ - 2486 (树形dp)
题目链接: D - 树形dp POJ - 2486 题目大意:一颗树,n个点(1-n),n-1条边,每个点上有一个权值,求从1出发,走V步,最多能遍历到的权值 学习网址:https://blog.c ...
- Apple Tree POJ - 2486
Apple Tree POJ - 2486 题目大意:一棵点带权有根树,根节点为1.从根节点出发,走k步,求能收集的最大权值和. 树形dp.复杂度可能是O(玄学),不会超过$O(nk^2)$.(反正这 ...
- 【POJ 2486】 Apple Tree(树型dp)
[POJ 2486] Apple Tree(树型dp) Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8981 Acce ...
- 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 ...
- poj 2486( 树形dp)
题目链接:http://poj.org/problem?id=2486 思路:经典的树形dp,想了好久的状态转移.dp[i][j][0]表示从i出发走了j步最后没有回到i,dp[i][j][1]表示从 ...
- POJ 2486 Apple Tree(树形dp)
http://poj.org/problem?id=2486 题意: 有n个点,每个点有一个权值,从1出发,走k步,最多能获得多少权值.(每个点只能获得一次) 思路: 从1点开始,往下dfs,对于每个 ...
- POJ 2486 Apple Tree
好抽象的树形DP......... Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 6411 Accepte ...
- poj 2486 Apple Tree(树形DP 状态方程有点难想)
Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 9808 Accepted: 3260 Descri ...
- POJ 2486 Apple Tree(树形DP)
题目链接 树形DP很弱啊,开始看题,觉得貌似挺简单的,然后发现貌似还可以往回走...然后就不知道怎么做了... 看看了题解http://www.cnblogs.com/wuyiqi/archive/2 ...
随机推荐
- bzoj3673 & bzoj3674 & 洛谷P3402 可持久化并查集
题目:bzoj3673:https://www.lydsy.com/JudgeOnline/problem.php?id=3673 bzoj3674:https://www.lydsy.com/Jud ...
- Python可迭代序列排序总结
列表排序 示例:lst = [12, 6, 1, 3, 10] 方法一:使用sort def list_sort(lst): lst.sort() # 就地排序,没有返回值 return lst 补充 ...
- ACM_名字的价值
名字的价值 Time Limit: 2000/1000ms (Java/Others) Problem Description: 集训终于开始了,参加集训的人很多,也就有很多名字,集训组织者发现了一件 ...
- ie9长度兼容
onchange="this.value=this.value.substring(0, 10)" onkeydown="this.value=this.value.su ...
- Ubuntu中在终端进入root权限但是总提示密码错误的解决方案
先解除root锁定,为root用户重新设置密码 打开终端输入:sudo passwd(注意是passwd不是password) Password: <--- 输入你当前用户的密码 Enter n ...
- C#屏蔽Alt+F4,解决Alt+F4关闭窗体时对话框NO后,线程不退出问题
//1.将窗体的属性KeyPrieview设置为true //keypreview属性为true的时候,就可以响应键盘事件v //2.在窗体KeyDown事件中加如下代码 private void F ...
- WM消息大全
消息名 消息值 说明 WM_CREATE 0x0001 应用程序创建一个窗口 WM_DESTROY 0x0002 一个窗口被销毁 WM_MOVE 0x0003 移动一个窗口 WM_SIZE 0x000 ...
- 如何修改yii2.0用户登录使用的user表为其它的表
这只是自己练习的一个记录而已. 因为某种原因,不想用yii自带的user表,想用自己建的admin数据库表,修改如下: 1. 参考高级模板里里的common\models\User 修改 Admi ...
- CNN结构:MXNet设计和实现简介
对原文有大量修改,如有疑惑,请移步原文. 参考链接:MXNet设计和实现简介 文章翻译于:https://mxnet.incubator.apache.org/architecture/index.h ...
- spring学习地址
http://developer.51cto.com/art/201006/205212_2.htm