poj2486

又是树形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 }
View Code
原文地址:https://www.cnblogs.com/i-caigou-TT/p/13848626.html