平衡二叉树,顾名思义就是一棵“平衡”的二叉树。在这道题中,“平衡”的定义为,对于树中任意一个节点,都满足左右子树的高度差不超过 d. 空树的高度定义为0,单个节点的高度为1,其他情况下树的高度定义为根节点左右子树高度最大值 + 1. 一棵在高度上平衡的树,节点数可能不平衡,因此再定义一棵树的不平衡度为这棵树中所有节点的左右子树的节点数之差的最大值。
给定平衡的定义参数d, 你需要求出所有高度为 n 的平衡树中不平衡度的最大值。
输入描述:
两个整数,n, d.
输出描述:
一个整数:所有高度为 n 的平衡树中不平衡度的最大值。
示例1
输入
4 1
输出
5
说明
下面这棵树在 d=1 的定义下高度是平衡的,其不平衡度为 5。
备注:
0 ≤ n, d ≤ 60
思路:这种题,肯定是找规律啦。然后就死活找不到而已.....
结合树的特性,每个节点都可以看成一个小树,然后这个n层的树就可以分解成2个n-1层的树。所以这个问题就分解成了左边是满二叉树,右边是一个二叉树,那么想要节点差最大,那右边就应该满足d的情况下形成一个较畸形的树。换句话说就是右边的形状是固定的,可继续分解的。且右边下的2个子树也满足这个条件。因为高度差为d
所以分解为f(n-1)+f(n-d-1),就是左+右,就OK了
注意:虽然数据小<=60,但是限时1s,直接DFS爆搜是不行的,考虑树分支的多次重复计算,可以使用记忆化搜索,和dp一样的,递推与递归实现而已。
代码如下:
#include<bits/stdc++.h>
using namespace std;
long long int dp[100];
int d;
long long int fun(int n)
{
if(n<=0) return 0;
if(dp[n]!=-1) return dp[n];
return dp[n]=fun(n-1)+fun(n-d-1)+1;
}
long long q_pow(long long int a,long long int b)
{
long long int sum=1;
while(b)
{
if(b&1)
sum=(sum*a);
a=(a*a);
b>>=1;
}
return sum;
}
int main()
{
int n;
fill(dp,dp+100,-1);
scanf("%d%d",&n,&d);
printf("%lld",q_pow(2,n-1)-1-fun(n-d-1));
return 0;
}