题目:二叉苹果树
思路:
树形dp/记忆化搜索。
f[i][j]
f
[
i
]
[
j
]
表示以
i
i
为根,其中需要保留个分叉点最多可保留多少个苹果。
转移方程:
f[i][j]=max(f[ch1][k]+w1+f[ch2][j−k−1]+w2)
f
[
i
]
[
j
]
=
m
a
x
(
f
[
c
h
1
]
[
k
]
+
w
1
+
f
[
c
h
2
]
[
j
−
k
−
1
]
+
w
2
)
其中,当
k=0
k
=
0
时,
w1=0
w
1
=
0
;当
k=j−1
k
=
j
−
1
时,
w2=0
w
2
=
0
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 100
struct Pair{
int x,y;
Pair(){}
Pair(int xx,int yy) {
x=xx,y=yy;
}
};
int n,m;
vector<Pair> tr[maxn+5];
vector<Pair> g[maxn+5];
int fa[maxn+5];
void find(int x) {
for(int i=0;i<tr[x].size();i++) {
Pair y=tr[x][i];
if(y.x==fa[x]) continue;
g[x].push_back(y);
fa[y.x]=x;
find(y.x);
}
}
int f[maxn+5][maxn+5];
int dp(int x,int y) {
if(g[x].size()==0||y==0) return 0;
if(f[x][y]) return f[x][y];
Pair ch1=g[x][0],ch2=g[x][1];
for(int i=0;i<y;i++) {
f[x][y]=max((i==0?0:ch1.y)+(i==y-1?0:ch2.y)+dp(ch1.x,i)+dp(ch2.x,y-1-i),f[x][y]);
}
return f[x][y];
}
int main() {
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
tr[x].push_back(Pair(y,z));
tr[y].push_back(Pair(x,z));
}
find(1);
int ans=dp(1,m+1);
printf("%d",ans);
return 0;
}