poj 2486 树形dp
2014-08-10 13:31
423 查看
又是一道好题。感觉很经典的树形dp。
由于走k步可能会重新返回节点。所以要设一下状态,否则无法进行状态转移。
f[0][r][k]表示以r为跟,走k步不回到r最多摘得的苹果数。
f[1][r][k]表示以r为根,走k步回到r最多摘得的苹果数。
那么:
f[1][r][k+2] = max(f[1][r][k+2], f[1][r][k-p] + f[1][son(r)][p]); //这个比较好想到,后边的要好好思考一下,容易漏掉;
f[0][r][k+2] = max(f[0][r][k+2], f[1][son(r)][p] + f[0][r][k-p]); //这个也没什么问题吧;
f[0][r][k+1] = max(f[0][r][k+1], f[1][r][k-p] + f[0][son(r)][p]); //这个是最容易漏掉的。想到了这个,这道题才算是完美了。
第二个转移方程表示从r到son(r)求出f[1][son(r)][..]并回到r,然后再从其它的子树中找不回来的最优值f[0][r][k-p],取其最大;
最后一个是从r到其他子树又回来,然后再到son(r)这个子树,不回来,取其最大。
代码实现的时候注意题目给的是无根树,在深搜的时候要注意标记已经访问过的节点(它们是未访问节点的父辈们),这样就变成了有根树。
代码如下:
由于走k步可能会重新返回节点。所以要设一下状态,否则无法进行状态转移。
f[0][r][k]表示以r为跟,走k步不回到r最多摘得的苹果数。
f[1][r][k]表示以r为根,走k步回到r最多摘得的苹果数。
那么:
f[1][r][k+2] = max(f[1][r][k+2], f[1][r][k-p] + f[1][son(r)][p]); //这个比较好想到,后边的要好好思考一下,容易漏掉;
f[0][r][k+2] = max(f[0][r][k+2], f[1][son(r)][p] + f[0][r][k-p]); //这个也没什么问题吧;
f[0][r][k+1] = max(f[0][r][k+1], f[1][r][k-p] + f[0][son(r)][p]); //这个是最容易漏掉的。想到了这个,这道题才算是完美了。
第二个转移方程表示从r到son(r)求出f[1][son(r)][..]并回到r,然后再从其它的子树中找不回来的最优值f[0][r][k-p],取其最大;
最后一个是从r到其他子树又回来,然后再到son(r)这个子树,不回来,取其最大。
代码实现的时候注意题目给的是无根树,在深搜的时候要注意标记已经访问过的节点(它们是未访问节点的父辈们),这样就变成了有根树。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; #define MAX 111 int N,K; int ans; int val[MAX],dp[2][MAX][2*MAX]; bool vis[MAX]; vector<int> tree[MAX]; void DP(int r) { int i,j,k; dp[1][r][0]=dp[0][r][0]=val[r]; vis[r]=1; int num=tree[r].size(); for(i=0;i<num;i++) { int v=tree[r][i]; if(vis[v]) continue; DP(v); for(k=K;k>=0;k--) { for(j=0;j<=k;j++) { dp[0][r][k+2]=max(dp[0][r][k+2],dp[1][v][k-j]+dp[0][r][j]); dp[0][r][k+1]=max(dp[0][r][k+1],dp[0][v][k-j]+dp[1][r][j]); dp[1][r][k+2]=max(dp[1][r][k+2],dp[1][v][k-j]+dp[1][r][j]); } } } } int main() { int i,j; int s,t; while(scanf("%d%d",&N,&K)!=EOF) { memset(vis,0,sizeof(vis)); memset(dp,0,sizeof(dp)); for(i=0;i<=N;i++) tree[i].clear(); for(i=1;i<=N;i++) { scanf("%d",&val[i]); } if(N==1) {printf("%d\n",val[1]);continue;} for(i=1;i<N;i++) { scanf("%d%d",&s,&t); tree[s].push_back(t); tree[t].push_back(s); } int root=1; DP(root); ans=max(dp[1][1][K],dp[0][1][K]); printf("%d\n",ans); } return 0; }
相关文章推荐
- POJ - 2486 Apple Tree(树形DP)
- poj 2486 Apple Tree(树形DP,状态好纠结。。。)
- POJ 2486 Apple Tree(树形DP)
- POJ 2486 Apple Tree(树形dp)
- poj 2486 Apple Tree (树形背包dp)
- poj 2486 Apple Tree(树形dp)
- poj 2486 (树形DP)
- POJ 2486 树形背包DP Apple Tree
- poj 2486(树形dp)
- POJ 2486 Apple Tree 树形dp
- POJ 2486 Apple Tree (树形dp)
- poj 2486 apple tree 树形DP 不懂的一定把你讲懂
- poj 2486 树形dp(给定步数 走一棵树,获得的节点值总和的最大值)
- POJ--2486--Apple Tree--树形回溯DP
- poj 2486 Apple Tree (树形背包dp)
- 树形DP______Apple Tree( POJ 2486 )
- poj 2486 Apple Tree(树形DP 状态方程有点难想)
- poj 2486 树形DP n选m连续路径
- POJ 2486 Apple Tree (树形dp 经典题)
- POJ 2486 Apple Tree(树形DP + 01背包)