第一次做二叉树相关的题目,而且动态规划不怎么会做。整个过程都很懵逼,按照网上的想法自己实现了一遍。
动态规划的思路为 rmv(rt, m) = max{rmv(leftc, a), rmv(rightc, b)} + value[rt]
其中a + b = m - 1, m意为, 以rt为父节点的子树中的节点个数之和。
将树节点到父节点的树枝苹果数作位该树节点的权值。
代码如下:
#include<iostream>
#include<fstream>
#include<math.h>
using namespace std;
#define N 100 + 5
typedef struct
{
int lchld;
int rchld;
int count;
} Bitree;
Bitree tree[N];
int val[N][N] = {0};
int values[N] = { 0 };
bool vis[N] = { false };
int dp[N][N];
/*生成二叉苹果树的函数*/
void build(int rt, int n)
{
vis[rt] = true;
int i = 1;
while (i <= n)
{
if (!vis[i] && val[rt][i] != 0)
{
if (!tree[rt].lchld)
{
tree[rt].lchld = i;
values[i] = val[rt][i];
}
else
{
tree[rt].rchld = i;
values[i] = val[rt][i];
}
build(i, n);
}
i++;
}
}
int max(int a, int b)
{
return a > b ? a : b;
}
int rmv_branches(int rt, int m) //这一个方法对于我来说有点绕
{
if (m == 0)
// return dp[rt][0]=values[rt];
return 0;
if (rt == 0)
return 0;
if (dp[rt][m] != -1)
return dp[rt][m];
for (int k = 0; k <= m - 1; k++)
{
if (tree[tree[rt].lchld].count >= k && tree[tree[rt].rchld].count >= m-1-k) //左子树节点总数大于等于k,且右子树节点总数大于m-1-k时,才参与计算。
{
int left, right;
left = rmv_branches(tree[rt].lchld, k);
right = rmv_branches(tree[rt].rchld, m - 1 - k);
dp[rt][m] = max(dp[rt][m], left + right + values[rt]);
}
}
return dp[rt][m];
}
/*后序遍历二叉树的函数,对每个节点的包括自己在内的子节点计数*/
int pro_traverse_bitree(int rt)
{
if (rt == 0)
return 0;
return tree[rt].count = 1 + pro_traverse_bitree(tree[rt].lchld) + pro_traverse_bitree(tree[rt].rchld);
}
int main()
{
memset(dp, -1, sizeof(dp));
int n, q;
cin >> n >> q;
for (int i = 1; i < n; i++)
{
int end1, end2,tempvalue;
cin >> end1 >> end2 >> tempvalue;
val[end1][end2] = val[end2][end1] = tempvalue;
}
build(1, n);
tree[0].count = 0;
pro_traverse_bitree(1);
cout<<rmv_branches(1, q + 1);
return 0;
}