您的位置:首页 > 其它

poj 2486 (树形DP)

2013-07-19 19:47 253 查看
poj 2486

题目:http://poj.org/problem?id=2486

题意:有一棵树,每个节点有一些苹果,人从1号节点出发,最多走K步,问你最多能吃到多少苹果。

思路:很好的一道题。俗话说好马不吃回头草,这道题目的难点就在于看到走回头路,并如何处理好这个DP。如果不用考虑走回头路,那么这题也太简单了吧,第一遍我就是这么做的 ,  = = WA了。。 考虑回头路,那么需要增设一维,表示人还在不在该节点。状态方程为:

d[u][j][0] = max(d[v][k][0]+d[u][j-k-2][0],d[u][j][0]);

d[u][j][1] = max(d[v][k][1]+d[u][j-k-1][0],d[u][j][1]);

d[u][j][1] = max(d[v][k][0]+d[u][j-k-2][1],d[u][j][1]);

d[u][j][0]表示以u为根节点的子树,走了j步,并且走完后人还留在u点。d[u][j][1]表示人不在u点了。



#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

const int MAXN = 111 ;

const int INF = 0x0fffffff ;

int n,m;

vector <int> G[MAXN];

int vis[MAXN],val[MAXN];

int d[MAXN][222][2];

void dfs(int u)
{
vis[u]=1;
for(int i=1;i<=m;i++)
d[u][i][0]=d[u][i][1]=-INF;
d[u][0][0]=val[u];
d[u][0][1]=val[u];
for(int i=0;i<G[u].size();i++)
{
int v = G[u][i];
if(vis[v]) continue;
dfs(v);
for(int j=m;j>=1;j--)
for(int k=0;k<=j-1;k++)
{
if(k<=j-2)
d[u][j][0] = max(d[v][k][0]+d[u][j-k-2][0],d[u][j][0]);
d[u][j][1] = max(d[v][k][1]+d[u][j-k-1][0],d[u][j][1]);
if(k<=j-2)
d[u][j][1] = max(d[v][k][0]+d[u][j-k-2][1],d[u][j][1]);
}
}
}

int main()
{
while(~scanf("%d%d",&n,&m))
{
for(int i=1;i<=n;i++)
scanf("%d",&val[i]);
int a,b;
for(int i=1;i<=n;i++)
G[i].clear();
for(int i=1;i<n;i++)
{
scanf("%d%d",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
}
memset(vis,0,sizeof(vis));
dfs(1);
int ans=0;
for(int i=0;i<=m;i++)
for(int j=0;j<=1;j++)
ans = max(ans,d[1][i][j]);
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: