又是树形dp,当然是用tag搜所以直接知道。
然后又开始在树上画画画看怎么转移。
这里问我们怎么吃更多苹果,那么不难想到,有时候需要走回头回到某棵子树的根来前往其他节点,所以我们列出三维状态:
dp[i][j][k]其中k=0,1 表示走到i这个点,花了j步,是否回到这个点能吃到的最大苹果数。
所以dp[u][j][1]=max(max(dp[v][k][0]+dp[u][j-k-2][1],dp[v][k][1]+dp[u][j-k-1][0]),dp[u][j][1]);
dp[u][j][0]=max(dp[v][k][0],dp[u][j-k-2][0]+dp[v][k][0]);
下附代码:
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 const int INF=0X3f3f3f3f; 5 int tot=0,head[1005],Next[2005],to[2005]; 6 int dp[1005][1005][2],n,k,a[1005]; 7 void add(int a,int b){ 8 Next[tot]=head[a],to[tot]=b; 9 head[a]=tot++; 10 } 11 void dfs(int x,int pre){ 12 for (int i=1; i<=k; i++){ 13 dp[x][i][0]=dp[x][i][1]=-INF; 14 } 15 dp[x][0][0]=dp[x][0][1]=a[x]; 16 for (int i=head[x]; i!=-1; i=Next[i]){ 17 int v=to[i]; 18 if (v!=pre){ 19 dfs(v,x); 20 } 21 } 22 for (int i=head[x]; i!=-1; i=Next[i]){ 23 int v=to[i]; 24 if (v!=pre){ 25 for (int j=k; j>=1; j--){ 26 for (int t=0; t<j; t++){ 27 if (t<=j-2){ 28 dp[x][j][0]=max(dp[v][t][0]+dp[x][j-t-2][0],dp[x][j][0]); 29 dp[x][j][1]=max(dp[v][t][0]+dp[x][j-t-2][1],dp[x][j][1]); 30 } 31 dp[x][j][1]=max(dp[v][t][1]+dp[x][j-t-1][0],dp[x][j][1]); 32 } 33 } 34 } 35 } 36 } 37 int main(){ 38 while (scanf("%d%d",&n,&k)!=EOF){ 39 tot=0; 40 for (int i=1; i<=n; i++){ 41 scanf("%d",&a[i]); 42 } 43 for (int i=1; i<=n; i++) head[i]=-1; 44 for (int i=1; i<n; i++){ 45 int x,y; 46 scanf("%d%d",&x,&y); 47 add(x,y); 48 add(y,x); 49 } 50 dfs(1,-1); 51 int res=0; 52 for (int i=0; i<=k; i++) 53 res=max(max(res,dp[1][i][1]),dp[1][i][0]); 54 printf("%d ",res); 55 } 56 }