链接:点击打开链接
题意:给出一棵树,没个节点有一个权值,求从节点1出发,最多走k步所得权值最大和
代码:
#include <vector>
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
int n,m,a[105],dp[105][205][2];
vector<int> G[105];
void dfs(int s,int fa){
int i,j,k,tmp;
for(i=0;i<G[s].size();i++){
tmp=G[s][i];
if(tmp==fa)
continue;
dfs(tmp,s);
for(j=m;j>=1;j--){
for(k=0;k<=m;k++){ //主要就是判断在当前子节点是否返回父节点
if(j-k-1>=0){
dp[s][j][1]=max(dp[s][j][1],dp[s][k][0]+dp[tmp][j-k-1][0]);
dp[s][j][1]=max(dp[s][j][1],dp[s][k][0]+dp[tmp][j-k-1][1]);
}
if(j-k-2>=0){
dp[s][j][1]=max(dp[s][j][1],dp[s][k][1]+dp[tmp][j-k-2][0]);
dp[s][j][0]=max(dp[s][j][0],dp[s][k][0]+dp[tmp][j-k-2][0]);
}
}
}
}
}
int main(){
int i,j,u,v,ans;
while(scanf("%d%d",&n,&m)!=EOF){ //dp[i][j][0]表示从i节点出发,走j步,
for(i=1;i<=n;i++) //返回i的最大值
G[i].clear(); //dp[i][j][1]表示从i节点出发,走j步,
memset(dp,0,sizeof(dp)); //不返回i的最大值
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
dp[i][0][0]=dp[i][0][1]=a[i];
}
for(i=1;i<n;i++){
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(1,-1);
ans=max(dp[1][m][0],dp[1][m][1]); //因为初始化的原因,所以不一定在m步最大
for(i=0;i<m;i++)
ans=max(ans,max(dp[1][i][0],dp[1][i][1]));
printf("%d\n",ans);
}
return 0;
}