poj2486解题报告
来源:互联网 发布:户外驴友用哪个软件 编辑:程序博客网 时间:2024/06/05 16:20
树形DP.
与以往一些分配资源的树形动归相比,这道题的最大不同就是可以往回走。。。即可以从子节点回到根节点。
建树问题:直接dfs在多叉树上做就可以。
设back[x][j]为从标号为x的根节点向下走j步,最终回到i所取得的最大价值;
设pass[x][j]为从标号为x的根节点向下走j步,最终不一定回到i所取得的最大价值。
这里(0<=j<=Max_step)
初始化:
for(i = 0 ; i <= Max_step ; ++i)
{
back[x][i] = pass[x][i] = val[x];
}
现在我们考虑为x的子节点son分配资源。下面设从节点son出发向下走的步数为k.(也即给节点son分配的资源)
换一种思考的方式,把son看作一部分,把根节点i剩余的子节点及以其为根的子树看作另一部分。
首先看back[x][j].
我们想要回到根节点i,把这个过程分为两个部分:
step1:从根节点x到达son,从son遍历son的子树再回到son,从son回到son的根节点x;
step2:用剩余的步数遍历根节点x其余的子树,再回到根节点x.
获得的价值:back[son][k] + back[x][j - k - 2]
为什么是j - k - 2呢,因为一共步数为j,从son往返消耗了步数2,在son处消耗了步数k,故还剩(j - 2 - k).
我们得到: back[x][j] = max(back[x][j] , back[son][k] + back[x][j - 2 - k]) (0<=k<=j-2)
接下来看pass[x][j].
既然不一定回到根节点x,那么最后的位置会是哪里呢?
我们刚才说过,要把以当前决策的子节点son为根节点的子树和根节点x的其余子树分开来考虑。
case1:
最后的位置在以子节点son为根节点的树上。
那么:
step1:从根节点遍历其余的子树,最终回到根节点;
step2:从根节点遍历以son为根节点的树,最终不一定回到son.
我们得到: pass[x][j] = max(pass[x][j] , pass[son][k] + back[x][j - 1 - k]) (0<=k<=j-1)
多出的那个“1”和上面类似,是从根节点x到子节点son的一步。
case2:
最后的位置在其余的子树上。
step1:从根节点遍历以son为根节点的子树,最终回到son,并回到根节点x.
strep2:从根节点出发遍历其余的子树,最终不一定回到son,不知所踪。
我们得到 : pass[x][j] = max(pass[x][j] , back[son][k] + pass[x][j - 2 - k]) (0<=k<=j-2)
状态转移方程大功告成。
还有一个重要问题:j的枚举顺序问题。用类似滚动数组一类东西从Max_size-0枚举。
与以往一些分配资源的树形动归相比,这道题的最大不同就是可以往回走。。。即可以从子节点回到根节点。
建树问题:直接dfs在多叉树上做就可以。
设back[x][j]为从标号为x的根节点向下走j步,最终回到i所取得的最大价值;
设pass[x][j]为从标号为x的根节点向下走j步,最终不一定回到i所取得的最大价值。
这里(0<=j<=Max_step)
初始化:
for(i = 0 ; i <= Max_step ; ++i)
{
back[x][i] = pass[x][i] = val[x];
}
现在我们考虑为x的子节点son分配资源。下面设从节点son出发向下走的步数为k.(也即给节点son分配的资源)
换一种思考的方式,把son看作一部分,把根节点i剩余的子节点及以其为根的子树看作另一部分。
首先看back[x][j].
我们想要回到根节点i,把这个过程分为两个部分:
step1:从根节点x到达son,从son遍历son的子树再回到son,从son回到son的根节点x;
step2:用剩余的步数遍历根节点x其余的子树,再回到根节点x.
获得的价值:back[son][k] + back[x][j - k - 2]
为什么是j - k - 2呢,因为一共步数为j,从son往返消耗了步数2,在son处消耗了步数k,故还剩(j - 2 - k).
我们得到: back[x][j] = max(back[x][j] , back[son][k] + back[x][j - 2 - k]) (0<=k<=j-2)
接下来看pass[x][j].
既然不一定回到根节点x,那么最后的位置会是哪里呢?
我们刚才说过,要把以当前决策的子节点son为根节点的子树和根节点x的其余子树分开来考虑。
case1:
最后的位置在以子节点son为根节点的树上。
那么:
step1:从根节点遍历其余的子树,最终回到根节点;
step2:从根节点遍历以son为根节点的树,最终不一定回到son.
我们得到: pass[x][j] = max(pass[x][j] , pass[son][k] + back[x][j - 1 - k]) (0<=k<=j-1)
多出的那个“1”和上面类似,是从根节点x到子节点son的一步。
case2:
最后的位置在其余的子树上。
step1:从根节点遍历以son为根节点的子树,最终回到son,并回到根节点x.
strep2:从根节点出发遍历其余的子树,最终不一定回到son,不知所踪。
我们得到 : pass[x][j] = max(pass[x][j] , back[son][k] + pass[x][j - 2 - k]) (0<=k<=j-2)
状态转移方程大功告成。
还有一个重要问题:j的枚举顺序问题。用类似滚动数组一类东西从Max_size-0枚举。
代码就比较水逼了。
#include<cstdio>#include<cstring>inline int max(int a , int b){return a > b ? a : b;}int pass[101][201] , back[101][201];int val[101];int n,m;int head[101] , next[202] , end[202] , ind;void addedge(int a , int b){int q = ++ind;end[q] = b;next[q] = head[a];head[a] = q;}bool ext[101];int n_son[101] , son[101][101];void build(int x){ext[x] = 1;for(int i = head[x] ; i ; i = next[i]){if(!ext[end[i]]){son[x][++n_son[x]] = end[i];build(end[i]);}}}void dfs(int x){int i,j,k;for(i = 0 ; i <= m ; ++i){pass[x][i] = back[x][i] = val[x];}for(i = 1 ; i <= n_son[x] ; ++i){dfs(son[x][i]);for(j = m ; j >= 0 ; --j){for(k = 0 ; k + 2 <= j ; ++k){back[x][j] = max(back[x][j] , back[son[x][i]][k] + back[x][j - 2 - k]);}for(k = 0 ; k + 2 <= j ; ++k){pass[x][j] = max(pass[x][j] , back[son[x][i]][k] + pass[x][j - 2 - k]);}for(k = 0 ; k + 1 <= j ; ++k){pass[x][j] = max(pass[x][j] , pass[son[x][i]][k] + back[x][j - 1 - k]);}}}}int main(){register int i;while(scanf("%d%d",&n,&m) != EOF){memset(pass , 0 , sizeof(pass));memset(back , 0 , sizeof(back));for(i = 1 ; i <= n ; ++i) scanf("%d",&val[i]);int a,b;ind = 0;memset(head , 0 , sizeof(head));memset(end , 0 , sizeof(end));memset(next , 0 , sizeof(next));for(i = 1 ; i < n ; ++i){scanf("%d%d",&a,&b);addedge(a , b);addedge(b , a);}memset(ext , 0 , sizeof(ext));memset(n_son , 0 , sizeof(n_son));build(1);dfs(1);printf("%d\n",max(pass[1][m] , back[1][m]));}return 0;}
0 0
- poj2486解题报告
- poj2486
- poj2486
- poj2486
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 【DP】poj2486
- Antiprime解题报告
- expr解题报告
- 华容道解题报告
- tju解题报告
- zju1062/pku1095解题报告
- UsacoGate解题报告 --- 序曲
- mac 下 sublime text 2 主要快捷键列表
- HDU 1026(bfs)
- 转载:GreenPlum的并行查询优化策略
- CSS禁止选择文本功能(兼容IE,火狐等浏览器)
- git学习笔记
- poj2486解题报告
- HDU 1032(水题)
- USB Phy/ULPI (2-读写USB Phy寄存器)
- 随便写了个堆排序程序
- iOS 第三方控件GIFView的学习记录
- 学习grep命令时候遇到的问题
- C++中cin、cin.get()、cin.getline()、getline()、gets()等函数的用法
- HDU 1039(水题)
- Cocos2d-x3.0(一)Cocos2d-x3.0简介以及创建新的Cocos2d-x跨平台工程