poj-2486-Apple Tree
| Time Limit: 1000MS | Memory Limit: 65536K | |
| Total Submissions: 11210 | Accepted: 3774 |
Description
Input
Output
Sample Input
2 1 0 11 1 2 3 2 0 1 2 1 2 1 3
Sample Output
11 2
Source
| 17857578 | 2486 | Accepted | 892K | 63MS | G++ | 1191B | 2017-11-18 19:26:17 |
树状DP。
本题的关键在于建立dp转化方程。
dp[x][j][0] = max( dp[x][j][0], dp[x][j-t][1] + dp[y][t-1][0] );
表示的是不回到当前x点的话,是回到j - t 步的x当前点 加上 不回到 y 点的步骤
dp[x][j][0] = max(dp[x][j][0], dp[x][j-t][0] + dp[y][t-2][1] );
表示的 不回到当前x点。 是 不回到当前 x 点 和 回到y点的 之和。
dp[x][j][1] = max(dp[x][j][1], dp[x][j-t][1] + dp[y][t-2][1] );
表示回到当前x点, 是回到x点和回到子结点y的总和。
// poj-2486
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
const int MAXN = 100 + 10;
int n, k, val[MAXN], vis[MAXN], dp[MAXN][2*MAXN][2];
vector<int> vt[MAXN];
void dfs(int x){
vis[ x ] = 1;
for(int i=0; i<vt[x].size(); ++i){
int y = vt[x][i];
if(vis[ y ] == 1){
continue;
}
dfs(y);
for(int j=k; j>=1; --j){
for(int t=1; t<=j; ++t){
dp[x][j][0] = max( dp[x][j][0], dp[x][j-t][1] + dp[y][t-1][0] );
if(t >= 2){
dp[x][j][0] = max(dp[x][j][0], dp[x][j-t][0] + dp[y][t-2][1] );
dp[x][j][1] = max(dp[x][j][1], dp[x][j-t][1] + dp[y][t-2][1] );
}
}
}
}
}
int main(){
freopen("in.txt", "r", stdin);
int a, b, ans;
while(scanf("%d %d", &n, &k) != EOF){
memset(dp, 0, sizeof(dp));
memset(vis, 0, sizeof(vis));
for(int i=1; i<=n; ++i){
scanf("%d", &val[i]);
for(int j=0; j<=k; ++j){
dp[i][j][0] = dp[i][j][1] = val[i];
}
}
for(int i=1; i<=n; ++i){
vt[i].clear();
}
for(int i=1; i<n; ++i){
scanf("%d %d", &a, &b);
vt[a].push_back(b);
vt[b].push_back(a);
}
dfs(1);
ans = max(dp[1][k][0], dp[1][k][1]);
printf("%d\n", ans );
}
return 0;
}
原文:http://www.cnblogs.com/zhang-yd/p/7857718.html