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; 
}

  

转载于:https://www.cnblogs.com/tanyalew/p/5984863.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值