timus.1018 二叉苹果树
第一次做二叉树相关的题目,而且动态规划不怎么会做。整个过程都很懵逼,按照网上的想法自己实现了一遍。
动态规划的思路为 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; }