习题:Maximum Weight Subset(树DP)
题目
思路
跟距离相关的多半要将距离加入DP状态的定义之中
我们设\(dp[i][j]\)表示以i为根节点的子树距离i最近的选的点的距离大于j的最小权值
我们可以考虑枚举两个儿子来构造距离大于k的情况,
注意距离要从0开始,毕竟要要将i考虑进DP里面
代码
#include<iostream>
#include<vector>
using namespace std;
int n,k;
int val[205];
long long dp[205][205];
/*
以i为根节点的子树,选的深度最小的点的深度大于j的最大权值
*/
vector<int> g[205];
void dfs(int u,int fa)
{
dp[u][0]=val[u];
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=fa)
{
dfs(v,u);
dp[u][0]+=dp[v][k];
}
}
for(int dep=1;dep<=n;dep++)
{
for(int i=0;i<g[u].size();i++)
{
int son1=g[u][i];
if(son1!=fa)
{
long long now=dp[son1][dep-1];
for(int j=0;j<g[u].size();j++)
{
int son2=g[u][j];
if(son2!=fa&&son2!=son1)
now+=dp[son2][max(dep-1,k-dep)];
}
dp[u][dep]=max(dp[u][dep],now);
}
}
}
for(int i=n-1;i>=0;i--)
dp[u][i]=max(dp[u][i],dp[u][i+1]);
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>val[i];
for(int i=1,u,v;i<n;i++)
{
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,0);
cout<<dp[1][0];
return 0;
}

浙公网安备 33010602011771号