dp[0][i][j]表示从i点出发,走最多j步返回i点的最优解。
dp[1][i][j]表示从i点出发,走最多j步不返回i点的最优解。
因此有:
dp[0][u][j+2]=max(dp[0][u][j+2],dp[0][v][p]+dp[0][u][j-p]); //从u点出发,分配p步给子节点v走且返回到v,分配j-p给u点走且回到u,用2步来回u和v。 dp[1][u][j+2]=max(dp[1][u][j+2],dp[0][v][p]+dp[1][u][j-p]); dp[1][u][j+1]=max(dp[1][u][j+1],dp[1][v][p]+dp[0][u][j-p]); dp[1][u][j+1]=max(dp[1][u][j+1],dp[0][v][p]+dp[0][u][j-p]);
最终答案为dp[1][1][k]。
//Memory:388K //Time:79ms #include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<iostream> using namespace std; int dp[2][110][210]; int n,k; int apple[110]; vector<int> G[110]; void init() { memset(dp,0,sizeof dp); for(int i=1;i<=n;++i) G[i].clear(); } void DFS(int fa,int u) { int v; for(int i=0;i<=k;++i) dp[0][u][i]=dp[1][u][i]=apple[u]; for(int i=0;i<G[u].size();++i) { v=G[u][i]; if(v==fa) continue; DFS(u,v); for(int j=k;j>=0;--j) { for(int p=0;p<=j;++p) { dp[0][u][j+2]=max(dp[0][u][j+2],dp[0][v][p]+dp[0][u][j-p]); dp[1][u][j+2]=max(dp[1][u][j+2],dp[0][v][p]+dp[1][u][j-p]); dp[1][u][j+1]=max(dp[1][u][j+1],dp[1][v][p]+dp[0][u][j-p]); dp[1][u][j+1]=max(dp[1][u][j+1],dp[0][v][p]+dp[0][u][j-p]); } } } } int main() { int a,b; while(scanf("%d%d",&n,&k)==2) { for(int i=1;i<=n;++i) scanf("%d",apple+i); init(); for(int i=1;i<n;++i) { scanf("%d%d",&a,&b); G[a].push_back(b); G[b].push_back(a); } DFS(-1,1); printf("%d\n",dp[1][1][k]); } }