题目大意:
给出一个有n个节点的树,每个节点上有个权值,问不超过k步最多能遍历到的权值。
输入: 输入n和k,然后是n个节点的值,然后是n-1个i j代表了i和j节点相邻。
输出:最多能遍历到的权值。
思路:树形dp:d[0][x][j+2] = max(d[0][x][j+2],d[0][v][k]+d[0][x][j-k]);
d[1][x][j+2] = max(d[1][x][j+2],d[0][v][k]+d[1][x][j-k]);
d[1][x][j+1] = max(d[1][x][j+1],d[1][v][k]+d[0][x][j-k]);
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
int d[2][105][205],a[105],t[105],b[105][105],n,m;//数组定大了会TLE
bool c[105];
void ans(int x){//dfs
int i,j,k,v;
for(i=0;i<=m;i++)
d[0][x][i]=d[1][x][i]=a[x];
c[x]=1;
for(i=1;i<=t[x];i++){
v=b[x][i];
if(0==c[v]){
ans(v);
for(j=m;j>=0;j--)//树形dp
for(k=0;k<=j;k++){
d[0][x][j+2] = max(d[0][x][j+2],d[0][v][k]+d[0][x][j-k]);
d[1][x][j+2] = max(d[1][x][j+2],d[0][v][k]+d[1][x][j-k]);
d[1][x][j+1] = max(d[1][x][j+1],d[1][v][k]+d[0][x][j-k]);
}
}
}
}
int main(){
int i,j,k,x,y;
while(scanf("%d%d",&n,&m)!=EOF){
memset(d,0,sizeof(d)); //清空
memset(b,0,sizeof(b));
memset(t,0,sizeof(t));
memset(c,0,sizeof(c));
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<n;i++){
scanf("%d%d",&x,&y);//读入
b[x][++t[x]]=y;
b[y][++t[y]]=x;
}
ans(1);
printf("%d\n",d[1][1][m]);//输出1-n的最大值
}
return 0;
}
本程序为博主亲自写且ac的,请勿抄袭。