Wannafly summer camp Day5 —— 平衡二叉樹(DFS)
阿新 • • 發佈:2018-12-17
9546: 平衡二叉樹 時間限制: 1 Sec 記憶體限制: 128 MB 提交: 115 解決: 33 [提交] [狀態] [討論版] [命題人:admin] 題目描述 平衡二叉樹,顧名思義就是一棵“平衡”的二叉樹。在這道題中,“平衡”的定義為,對於樹中任意一個節點,都滿足左右子樹的高度差不超過 d. 空樹的高度定義為0,單個節點的高度為1,其他情況下樹的高度定義為根節點左右子樹高度最大值 + 1。 一棵在高度上平衡的樹,節點數可能不平衡。再定義一棵樹的不平衡度為這棵樹中所有節點的左右子樹的節點數之差的最大值。 給定平衡的定義引數d, 你需要求出所有高度為 n 的平衡樹中不平衡度的最大值。
輸入 兩個整數,n,d(0≤n,d≤60).
輸出 一個整數:所有高度為 n 的平衡樹中不平衡度的最大值。
樣例輸入
4 1
樣例輸出
5
提示
下面這棵樹在 d=1 的定義下高度是平衡的,其不平衡度為 5。
來源/分類
Wannafly summer camp Day5
解題思路: 從給出的樣例中可以很快的出,只要左邊構建完全二叉樹,右邊在滿足 “樹中任意一個節點,都滿足左右子樹的高度差不超過 d”情況下節點儘可能少,那麼左樹減去右樹就能得到最大不平衡度。
完全二叉左樹 在高度為n下的節點數為 2^n 右邊貪心建樹 ,只需要遞迴著不斷為新的右子樹新增滿足與左樹的高度差不超過d的節點並統計就ok
/*
* @Author: Achan
* @Date: 2018-10-25 18:49:42
* @Last Modified by: Achan
* @Last Modified time: 2018-10-26 15:59:02
*/
#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<vector>
#include<queue>
#include<cmath>
using namespace std;
#define X first
#define Y second
#define eps 1e-2
#define gcd __gcd
#define pb push_back
#define PI acos(-1.0)
#define lowbit(x) (x)&(-x)
#define fin freopen("in.txt","r",stdin);
#define fout freopen("out.txt","w",stdout);
#define bug printf("!!!!!\n");
#define mem(x,y) memset(x,y,sizeof(x))
#define rep(i,j,k) for(int i=j;i<(int)k;i++)
#define per(i,j,k) for(int i=j;i<=(int)k;i++)
#define io std::ios::sync_with_stdio(false),cin.tie(NULL),cout.tie(NULL);
typedef long long ll;
typedef long double LD;
typedef pair<int,int> pii;
typedef unsigned long long ull;
const int inf = 1<<30;
const ll INF = 1e18 ;
const int mod = 1e9+7;
const int maxn = 1e5+2;
ll a[100];
int n,d;
ll DFS(int u)
{
if(a[u] != -1) return a[u];
ll ret = 0;
int cur = u;
while( cur - d >= 2)
{
a[cur - d - 1] = DFS(cur - d -1); //記憶化 存一下右邊樹總共需要新增的節點數
ret += (cur - d - 1) + a[cur - d - 1];
cur--; //左樹高度降低1
}
//a[u] = ret;
return ret;
}
int main(void)
{
cin>>n>>d;
if(n==0 ) return !puts("0");
ll ans = 0;
ans = (1LL<<(n-1) ) - 1; //減去根節點
mem(a,-1);
if(n - 1 - d >= 0) ans -= DFS(n -1 - d);
cout<<ans - (max( (n - d - 1) , 0 )) <<endl;
}