首页 > 代码库 > POJ 2486 Apple Tree
POJ 2486 Apple Tree
很好也很烦的一个树形DP,昨天搞了一晚上是在想不出,后来没办法去看题解了,完事发现非常令人感动的是,我一开始设的状态都错了,然后就一直错了下去,还好及时的回头是岸了。
不说废话了,正题:
题目大意:给一棵树,n个节点,每个节点有一个权值,要求从节点1出发最多走k步,求所经过的点的权值和的最大值,每个点经过一次后就变为0;
最近做了一些树DP 也小小的总结了点规律,树形dp一般是设dp[rt][j]即以rt为根的子树j状态。这个题可以设
dp[rt][j][0]表示以rt为根的子树走j步最后不回到rt的解
dp[rt][j][1]表示以rt为根的子树走j步最后回到rt的解
方程看代码
然后对于每个儿子节点进行一次背包,背包容量为步数,看了半天题解一直感觉方程根本就不对,后来看到了是背包,(个人对于背包的一个描述就是放与不放的问题),想了一下恍然大悟
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <iostream> 5 #include <algorithm> 6 #include <vector> 7 #include <cmath> 8 #include <map> 9 #define INF 0x3f3f3f3f10 typedef __int64 LL;11 const int maxn = 110;12 const int maxv = 210;13 using namespace std;14 int dp[maxn][maxv][2],a[maxn];15 vector<int>son[maxn];16 vector<int>f[maxn];17 bool vis[maxn];18 int n,m;19 void build_tree(int rt)20 {21 //个人比较中意的一种建树的方法22 //首先用辅助vector f记录总共有多少条边,然后再从根节点开始dfs23 //找出与rt相连的边让其成为rt的子节点,然后vis标记这条边已经属于子节点24 //不能再成为别的节点的子节点25 //最后son[rt]中的元素都是rt的子节点26 //这样做主要还是不太会用邻接表 渣渣为自己找借口。。27 int len = f[rt].size(),x;28 for(int i = 0;i<len;++i)if(!vis[x = f[rt][i]]){29 son[rt].push_back(x);30 vis[x] = 1;31 build_tree(x);32 }33 }34 void init()35 {36 memset(vis,0,sizeof(vis));37 memset(son,0,sizeof(son));38 memset(f,0,sizeof(f));39 for(int i = 1;i<=n;++i)scanf("%d",a+i);40 for(int i = 1;i<n;++i)41 {42 int s,t;43 scanf("%d%d",&s,&t);44 f[s].push_back(t);45 f[t].push_back(s);46 }47 for(int i = 1;i<=n;++i)48 for(int j = 0;j<=m;++j)49 dp[i][j][0] = dp[i][j][1] = a[i];50 vis[1] = 1;51 build_tree(1);52 }53 void dfs(int rt)54 {55 int len = son[rt].size();56 for(int i = 0;i<len;++i){57 int u = son[rt][i];58 dfs(u);59 for(int j = m;j>=0;--j){60 for(int k = 0;k<=j;++k){61 //从rt走到u最后还回到rt 因为还要回到rt 所以rt->u 和u->rt这两步要排除62 if(k-2>=0)dp[rt][j][1] = max(dp[rt][j][1],dp[rt][j-k][1]+dp[u][k-2][1]);63 //从rt走到u最后不回来 也就是把k-1大小的物品放入背包中 (k-1 是因为rt->u排除)64 if(k-1>=0)dp[rt][j][0] = max(dp[rt][j][0],dp[rt][j-k][1]+dp[u][k-1][0]);65 //从rt走到u还回来 最后停在别的儿子节点上66 if(k-2>=0)dp[rt][j][0] = max(dp[rt][j][0],dp[rt][j-k][0]+dp[u][k-2][1]);67 }68 }69 }70 }71 int main()72 {73 // freopen("in.txt","r",stdin);74 while(cin>>n>>m)75 {76 init();77 dfs(1);78 cout<<max(dp[1][m][0],dp[1][m][0])<<endl;79 }80 return 0;81 }
POJ 2486 Apple Tree
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。