您的位置:首页 > 其它

poj 2486 树形dp

2013-08-12 10:41 344 查看
思路:这题是裸的树形dp。dp[i][j]表示第i个节点花费j步并且从子节点返回,能得到的最大苹果数;nback[i[j]表示第i个节点花费j步并且进入某个子节点不返回,能得到的最大苹果数。那么我们就能得到动态方程:

根节点为u,子节点为v

dp[u][j]=max(dp[u][j],dp[u][j-k-2]+dp[v][k]);
nback[u][j]=Max(nback[u][j],nback[u][j-k-2]+dp[v][k],dp[u][j-k-1]+nback[v][k]);//表示对某个节点可以选择进入返回或不返回.

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
#define Maxn 210
using namespace std;
int vi[Maxn],val[Maxn],dp[Maxn][Maxn],n,m,nback[Maxn][Maxn];
vector<int> head[Maxn];
void init()
{
memset(vi,0,sizeof(vi));
memset(val,0,sizeof(val));
memset(dp,0,sizeof(dp));
memset(nback,0,sizeof(nback));
for(int i=0;i<=110;i++)
head[i].clear();
}
inline int Max(int a,int b,int c)
{
int temp=a>b?a:b;
return temp>c?temp:c;
}
void add(int u,int v)
{
head[u].push_back(v);
head[v].push_back(u);
}
void dfs(int u)
{
int i,v,sz,j,k;
vi[u]=1;
sz=head[u].size();
int s1,s2;
s1=s2=0;
for(i=0;i<sz;i++)
{
v=head[u][i];
if(vi[v]) continue;
dfs(v);
for(j=m;j>=1;j--){
s1=s2=0;
for(k=0;k<=j-1;k++){
if(j-k>=2)
s1=max(s1,dp[u][j-k-2]+dp[v][k]);
s2=Max(s2,nback[u][j-k-2]+dp[v][k],dp[u][j-k-1]+nback[v][k]);
}
dp[u][j]=max(dp[u][j],s1);
nback[u][j]=max(nback[u][j],s2);
}
}
for(i=0;i<=m;i++)
dp[u][i]+=val[u];
for(i=0;i<=m;i++)
nback[u][i]+=val[u];
}
int main()
{
int i,j,a,b;
while(scanf("%d%d",&n,&m)!=EOF)
{
init();
for(i=1;i<=n;i++)
scanf("%d",val+i);
for(i=1;i<n;i++){
scanf("%d%d",&a,&b);
add(a,b);
}
dfs(1);
printf("%d\n",nback[1][m]);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: