您的位置:首页 > 移动开发

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。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  apple tree 存储 ini