生活随笔
收集整理的這篇文章主要介紹了
poj 2486 树形dp
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
思路:這題是裸的樹(shù)形dp。dp[i][j]表示第i個(gè)節(jié)點(diǎn)花費(fèi)j步并且從子節(jié)點(diǎn)返回,能得到的最大蘋(píng)果數(shù);nback[i[j]表示第i個(gè)節(jié)點(diǎn)花費(fèi)j步并且進(jìn)入某個(gè)子節(jié)點(diǎn)不返回,能得到的最大蘋(píng)果數(shù)。那么我們就能得到動(dòng)態(tài)方程:
根節(jié)點(diǎn)為u,子節(jié)點(diǎn)為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]);//表示對(duì)某個(gè)節(jié)點(diǎn)可以選擇進(jìn)入返回或不返回.
#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;
} ?
轉(zhuǎn)載于:https://www.cnblogs.com/wangfang20/p/3252450.html
總結(jié)
以上是生活随笔為你收集整理的poj 2486 树形dp的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。