pku 2486 Apple Tree(树形DP,双重DP)
2009-09-25 18:45
357 查看
题目:给定一棵树,每个节点上有一个权值,从节点1出发,可以移动k步,要使经过的节点的权值和最大。
分析:dp[i][j]表示从节点i出发,可以移动j步,不需要回到起点的情况;dp_back[i][j]表示从节点i出发,可以移动j步,需要回到起点的情况。首先可以确定最外层是树形DP,而里面则是一个背包的组合问题。
解答:输入中给定了节点见的邻接关系,但并未制定父子关系,根据节点1是树的根,先进行一遍深搜确定各节点间的父子关系。
然后则是处理DP问题了,这个问题有点小复杂,一不小心就出错了。
首先是dp_back[][],这个还比较好处理,经典的背包问题。
但是dp[][]稍微有点不同。因为在root的所有分支中,有一条可以一去不复返,而其他的则需要回到起点。我是通过枚举一去不复返的那个子节点来做的,用了4个for。
分析:dp[i][j]表示从节点i出发,可以移动j步,不需要回到起点的情况;dp_back[i][j]表示从节点i出发,可以移动j步,需要回到起点的情况。首先可以确定最外层是树形DP,而里面则是一个背包的组合问题。
解答:输入中给定了节点见的邻接关系,但并未制定父子关系,根据节点1是树的根,先进行一遍深搜确定各节点间的父子关系。
然后则是处理DP问题了,这个问题有点小复杂,一不小心就出错了。
首先是dp_back[][],这个还比较好处理,经典的背包问题。
但是dp[][]稍微有点不同。因为在root的所有分支中,有一条可以一去不复返,而其他的则需要回到起点。我是通过枚举一去不复返的那个子节点来做的,用了4个for。
#include <vector> #include <iostream> #define _clr(a,b) memset(a,b,sizeof(a)) template<class T> void get_max(T& a,T b) { if(a<b) a=b;} using namespace std; int N,K; vector<int> edges[105]; vector<int> edges_temp[105]; int apple[105];//节点上苹果数量 bool visited[105]; int DP[105][205];//出发不需要返回起点 int DP_back[105][205];//出发后需要返回起点 int temp_DP_back[205]; void DFS(int root) { for(int i=0;i<edges[root].size();i++) DFS(edges[root][i]); for(int i=0;i<edges[root].size();i++) { for(int k=K;k>=1;k--) { for(int j=2;j<=k;j++) { get_max(DP_back[root][k],DP_back[edges[root][i]][j-2]+DP_back[root][k-j]);//需要返回的可以直接DP } } } for(int t=0;t<edges[root].size();t++)//枚举不返回的子节点 { for(int i=0;i<=K;i++) temp_DP_back[i]=apple[root]; for(int i=0;i<edges[root].size();i++) { if(i==t) continue; for(int k=K;k>=1;k--) { for(int j=2;j<=k;j++) { get_max(temp_DP_back[k],DP_back[edges[root][i]][j-2]+temp_DP_back[k-j]); } } } for(int k=1;k<=K;k++) { for(int j=1;j<=k;j++) get_max(DP[root][k],temp_DP_back[k-j]+DP[edges[root][t]][j-1]); } } } void DFS_2(int root)//深搜,用来确定孩子间的父子关系。在edges[i]中存储i的孩子。 { for(int i=0;i<edges_temp[root].size();i++) { if(!visited[edges_temp[root][i]]) { visited[edges_temp[root][i]]=true; edges[root].push_back(edges_temp[root][i]); DFS_2(edges_temp[root][i]); } } } int main() { int start,end; while(scanf("%d%d",&N,&K)!=EOF) { for(int i=1;i<=N;i++) { edges[i].clear(); edges_temp[i].clear(); } for(int i=1;i<=N;i++) { scanf("%d",&apple[i]); } for(int i=1;i<=N;i++) { for(int j=0;j<=K;j++) DP_back[i][j]=DP[i][j]=apple[i]; } for(int i=1;i<N;i++) { scanf("%d%d",&start,&end); edges_temp[start].push_back(end); edges_temp[end].push_back(start); } _clr(visited,0); visited[1]=true; DFS_2(1); DFS(1); printf("%d/n",DP[1][K]); } return 0; }
相关文章推荐
- 【树形dp】PKU-2486-Apple Tree
- POJ 2486 Apple Tree (树形dp)
- POJ 2486 树形背包DP Apple Tree
- 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 Apple Tree 树形DP
- POJ 2486 Apple Tree 树形dp
- poj 2486 Apple Tree (树形背包dp)
- POJ 2486 Apple Tree(树形DP)
- poj 2486 Apple Tree(DP-树形DP)
- POJ 2486 Apple Tree 树形DP
- POJ 2486 Apple Tree(树形DP + 01背包)
- POJ 2486 Apple Tree (树形dp 经典题)
- [树形dp] poj 2486 Apple Tree
- poj 2486 apple tree 树形DP 不懂的一定把你讲懂
- poj 2486-Apple Tree - 树形DP