Ural_1018. Binary Apple Tree(树形DP)

  /*第一道树形dp的题,感觉树形dp就是在dp的基础上加了树这个环境,建树——DFS。思想上还是基本的动态规划思想(最优子结构,重叠子问题)。参考解题报告终于把这题做出来的。

思路:dp[t][j]为以t为根的子树,保留j条边时的最优情况,map[i][j]为i结点到j结点构成的边的权值。

当t与一个孩子相连时:

dp[t][j] = max(dp[L][j-1]+map[L][t], dp[R][j-1] + map[r][t]);

当t结点与两个孩子相连时:

for(j = 0; j <= i-2; j++){ //因为j表示的是除去t -> L 和 t -> R两边之后两个子树的的子结构,所以 j = 0 to i - 2;

  dp[t][i] = max(dp[t][i], dp[L][j] + dp[R][i - j -2] + map[L][i] + map[R][i])

}

然后就是建树,dfs。。
*/

//My Code:

#include <iostream>
#include <cstring>
#include <fstream>

using namespace std;

const int N = 105;

struct node{
int l, r;
}node[N];

int dp[N][N], map[N][N], n, q;

void built_tree(int t){
int flag, i;
for(flag = 0, i = 1; i <= n; i++){
if(map[t][i] && !node[i].l && !node[t].r){
flag = 1;
//cout << "root " << t << endl;
if(!node[t].l){
node[t].l = i;
//cout << "l " << i << endl;
} else {
node[t].r = i;
//cout << "r " << i << endl;
break;
}
}
}
if(!flag) return;

built_tree(node[t].l);
built_tree(node[t].r);
}

void tree_dp(int t){
if(!node[t].l) return ;
int l, r, tmp, i, j;

l = node[t].l; r = node[t].r;
tree_dp(l); tree_dp(r);

dp[t][1] = max(map[l][t], map[r][t]);
tmp = map[l][t] + map[r][t];

for(i = 2; i <= q; i++){
dp[t][i] = max(dp[l][i-1] + map[t][l], dp[r][i-1] + map[t][r]);
for(j = 0; j < i-1; j++){
dp[t][i] = max(dp[t][i], dp[l][j] + dp[r][i-j-2] + tmp);
}
}
}

int main(){
//fstream cin("data.in");

int i, x, y, z;
while(cin >> n >> q){

memset(map, 0, sizeof(map));
memset(node, 0, sizeof(node));
memset(dp, 0, sizeof(dp));

for(i = 0; i < n-1; i++){
cin >> x >> y >> z;
map[x][y] = map[y][x] = z;
}
built_tree(1);
tree_dp(1);
cout << dp[1][q] << endl;
}
return 0;
}

原文地址:https://www.cnblogs.com/vongang/p/2205408.html