Topcoder SRM666 DIV2第三题,树形DP
2015-08-26 21:32
351 查看
题意:
给一个具有n个节点的树,每个节点上有一个值v,现在从节点1开始,走L步,问L步中经过的v值之和最大为多少。若一个点被重复走过,这个权值只计算一次。
范围:
1<n<=50,0<=L<=100,0<=v<=100。
树形DP解决,状态分析:
dp[u][1][step]:表示从节点u开始,走step步,此时回到u点,经过的点的最大权值之和。
dp[u][0][step]:表示从节点u开始,走step步,此时没有回到u点,经过的点的最大权值之和。
状态转移:
走step步回到u点,只有一种转移方法:child表示当前的子树,我们都从当前子树考虑,若能转移,当前子树也必须回到child点。所以转移方程为:
dp[u][1][step]=max(dp[u][1][step],dp[u][1][i]+dp[child][1][step-i-2]):dp[u][1][i]从前面的几个孩子求得的值,dp[child][1][step-i-2]当前孩子必须回到child点,-2表示u->child的边,来回的步数。
走step步没有回到u点,有两种转移方法:也是从当前子树考虑。若能转移,可以有两种情况:
①当前子树回到child点,前面考虑的子树没有回到u点;
dp[u][0][step]=max(dp[u][0][step],dp[u][0][i]+dp[child][1][step-i-2])
②当前子树没回到child点,前面考虑的子树回到了u点。
dp[u][0][step]=max(dp[u][0][step],dp[u][1][i]+dp[child][0][step-i-1])
大体思路如上,具体实现细节需要注意一下边界情况,还有在用一棵子树转移的时候,为了防止这棵子树跟自己本身的转移,导致有些点被重复采集,这里采用了tmp[][][]数组存储了当前子树更新了的一些状态,防止这些更新的状态被本棵树再次利用,这里主要是这目的,然后在对这棵树转移结束后,在用tmp数组更新dp数组。如下:
具体代码实现如下:
给一个具有n个节点的树,每个节点上有一个值v,现在从节点1开始,走L步,问L步中经过的v值之和最大为多少。若一个点被重复走过,这个权值只计算一次。
范围:
1<n<=50,0<=L<=100,0<=v<=100。
树形DP解决,状态分析:
dp[u][1][step]:表示从节点u开始,走step步,此时回到u点,经过的点的最大权值之和。
dp[u][0][step]:表示从节点u开始,走step步,此时没有回到u点,经过的点的最大权值之和。
状态转移:
走step步回到u点,只有一种转移方法:child表示当前的子树,我们都从当前子树考虑,若能转移,当前子树也必须回到child点。所以转移方程为:
dp[u][1][step]=max(dp[u][1][step],dp[u][1][i]+dp[child][1][step-i-2]):dp[u][1][i]从前面的几个孩子求得的值,dp[child][1][step-i-2]当前孩子必须回到child点,-2表示u->child的边,来回的步数。
走step步没有回到u点,有两种转移方法:也是从当前子树考虑。若能转移,可以有两种情况:
①当前子树回到child点,前面考虑的子树没有回到u点;
dp[u][0][step]=max(dp[u][0][step],dp[u][0][i]+dp[child][1][step-i-2])
②当前子树没回到child点,前面考虑的子树回到了u点。
dp[u][0][step]=max(dp[u][0][step],dp[u][1][i]+dp[child][0][step-i-1])
大体思路如上,具体实现细节需要注意一下边界情况,还有在用一棵子树转移的时候,为了防止这棵子树跟自己本身的转移,导致有些点被重复采集,这里采用了tmp[][][]数组存储了当前子树更新了的一些状态,防止这些更新的状态被本棵树再次利用,这里主要是这目的,然后在对这棵树转移结束后,在用tmp数组更新dp数组。如下:
tmp[u][1][i]=max(tmp[u][1][i],dp[u][1][j]+dp[child][1][i-j-2]);
tmp[u][0][i]=max(tmp[u][0][i],dp[u][1][j]+dp[child][0][i-j-1]);
<pre name="code" class="html">tmp[u][0][i]=max(tmp[u][0][i],dp[u][0][j]+dp[child][1][i-j-2]);
具体代码实现如下:
#include <vector> #include <list> #include <map> #include <set> #include <deque> #include <stack> #include <bitset> #include <algorithm> #include <functional> #include <numeric> #include <utility> #include <sstream> #include <iostream> #include <iomanip> #include <cstdio> #include <cmath> #include <cstdlib> #include <ctime> #include <cstring> using namespace std; #define N 55 class CollectingTokens { public: int maxTokens(vector <int>, vector <int>, vector <int>, int); vector<int> edge ; int val ; int st; int dp [2][105]; int tmp [2][105]; void dfs(int u,int v); void cal(int u,int child); void Copy(int u); }; void CollectingTokens::Copy(int u) { for(int i=0;i<=st;i++) { for(int j=0;j<=i;j++) { if((i-j-2>=0)&&(i%2==0)&&(j%2==0)) dp[u][1][i]=tmp[u][1][i]; if(i-j-1>=0) dp[u][0][i]=tmp[u][0][i]; if(i-j-2>=0) dp[u][0][i]=tmp[u][0][i]; } } } void CollectingTokens::cal(int u,int child) { for(int i=0;i<=st;i++) { tmp[u][1][i]=dp[u][1][i]; tmp[u][0][i]=dp[u][0][i]; for(int j=0;j<=i;j++) { if((i-j-2>=0)&&(i%2==0)&&(j%2==0)) tmp[u][1][i]=max(tmp[u][1][i],dp[u][1][j]+dp[child][1][i-j-2]); if(i-j-1>=0) tmp[u][0][i]=max(tmp[u][0][i],dp[u][1][j]+dp[child][0][i-j-1]); if(i-j-2>=0) tmp[u][0][i]=max(tmp[u][0][i],dp[u][0][j]+dp[child][1][i-j-2]); } } Copy(u); } void CollectingTokens::dfs(int u,int pr) { int len=edge[u].size(); int num=0,child; dp[u][1][0]=dp[u][0][0]=val[u]; for(int i=0;i<len;i++) { child=edge[u][i]; if(child==pr) continue; num++; dfs(child,u); cal(u,child); } if(num==0) { for(int i=0;i<=st;i++) { dp[u][1][i]=val[u]; dp[u][0][i]=val[u]; } } } int CollectingTokens::maxTokens(vector <int> A, vector <int> B, vector <int> tokens, int L) { int len=A.size(); for(int i=0;i<len;i++) { edge[A[i]].push_back(B[i]); edge[B[i]].push_back(A[i]); } for(int i=0;i<len+1;i++) val[i+1]=tokens[i]; st=L; memset(dp,0,sizeof(dp)); dfs(1,1); int ans=0; for(int i=0;i<=st;i++) ans=max(ans,max(dp[1][1][i],dp[1][0][i])); return ans; }
相关文章推荐
- CodeForces 339D Xenia and Bit Operations 线段树
- nginx之Web服务器集群-helloworld
- 跨域资源共享(CORS)安全性浅析[内有提及OPTIONS请求发起的条件]
- linux 根据sp和fp查调用栈
- V4L2驱动程序架构
- Linux用户管理
- 使用 Linux 的 strace 命令跟踪/调试程序的常用选项
- 使用 Linux 的 strace 命令跟踪/调试程序的常用选项
- Linux 硬连接 软连接
- heartbeat
- Linux登陆或者su - 用户慢问题
- Kali Linux中前十名的Wifi攻击工具
- 【Apache】ab工具
- centos6.7安装图文教程
- Linux脚本编写之sed用法
- Linux学习:安装CentOS 6.7以及CentOS 7.1
- 使用U盘安装Kali的曲折经历
- Linux Desktop Entry 文件深入解析
- 嵌入式linux内核制作
- nginx之Web服务器集群-基础知识