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

POJ 2486 Apple Tree(树形dp)

2017-06-27 15:14 309 查看
http://poj.org/problem?id=2486

题意:

有n个点,每个点有一个权值,从1出发,走k步,最多能获得多少权值。(每个点只能获得一次)

思路:

从1点开始,往下dfs,对于每个结点,把时间分配给它的子节点,然后求一个最大值。

但是要注意的是,它有可能会走了之后然后又走回到父亲结点,这样的话,状态转移方程需要多考虑一下。

d【u】【j】【0/1】表示从u结点出发走 j 时所能获得的最大权值(0/1表示是否返回u结点)。

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




#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<sstream>
#include<vector>
#include<stack>
#include<queue>
#include<cmath>
#include<map>
#include<set>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
const int INF = 0x3f3f3f3f;
const int maxn = 500+5;

int n, k;

int val[maxn];
int vis[maxn];

vector<int> g[maxn];

int d[maxn][maxn][2];

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

int main()
{
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n, &k))
{
for(int i=1;i<=1000;i++)  g[i].clear();
memset(d,0,sizeof(d));

for(int i=1;i<=n;i++)
{
scanf("%d",&val[i]);
for(int j=0;j<=k;j++)
d[i][j][0]=d[i][j][1]=val[i];
}

for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}

memset(vis,0,sizeof(vis));
dfs(1);
printf("%d\n",max(d[1][k][0],d[1][k][1]));
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: