[树形dp] Jzoj P1046 寻宝之旅
Posted comfortable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[树形dp] Jzoj P1046 寻宝之旅相关的知识,希望对你有一定的参考价值。
题解
- 又是一道树形dp,今天题做的要死了
- 题目说:
-
它们之间由一些小路相连,小路不会形成环,即两个宝藏点之间有且只有一条通路
- 显然就是棵树
- 容易得到设f[i][j]以i为根的子树,剩j的的最大价值
- 那就有两种情况:
- ①当前点不挖,直接跳
- ②当前点留一个人挖,可以向下派j-1个人
- 则有 f[i][j]=max(f[i][j],f[i][j-1-k]+f[son[i]][k]+v[i])
-
那么我们不知道在f[i][j-1-k]中是否有v[i],如果有就算重了
-
可以多定一个数组g,也可以多加一维,其实是一样的
-
g[i][j]表示 ]以i为根的子树,剩j,不挖i 的的最大价值
代码
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 using namespace std; 5 int n,m,cnt,v[110],f[110][110],to[210],from[210],head[110],k[110],g[110][110]; 6 void insert(int x,int y) { to[++cnt]=y; from[cnt]=head[x]; head[x]=cnt; } 7 void dp(int root,int fa) 8 { 9 f[root][1]=v[root]; 10 for (int w=head[root];w;w=from[w]) 11 if (to[w]!=fa) 12 { 13 dp(to[w],root); 14 for (int i=1;i<=m;i++) k[i]=max(f[root][i],f[to[w]][i]); 15 for (int i=1;i<=m;i++) 16 for (int j=1;j<i;j++) 17 k[i]=max(k[i],g[root][i-j-1]+f[to[w]][j]+v[root]); 18 for (int i=1;i<=m;i++) f[root][i]=k[i]; 19 for (int i=1;i<=m;i++) k[i]=max(f[to[w]][i],g[root][i]); 20 for (int i=1;i<=m;i++) 21 for (int j=1;j<i;j++) 22 k[i]=max(k[i],g[root][i-j]+f[to[w]][j]); 23 for (int i=1;i<=m;i++) g[root][i]=k[i]; 24 } 25 } 26 int main() 27 { 28 scanf("%d%d",&n,&m); 29 for (int i=1;i<=n;i++) scanf("%d",&v[i]); 30 for (int i=1;i<=n-1;i++) 31 { 32 int x,y; 33 scanf("%d%d",&x,&y); 34 insert(x,y); insert(y,x); 35 } 36 dp(1,0); 37 printf("%d",f[1][m]); 38 return 0; 39 }
以上是关于[树形dp] Jzoj P1046 寻宝之旅的主要内容,如果未能解决你的问题,请参考以下文章