#include <bits/stdc++.h>
using namespace std;
const int INF = 1000 * 1000 * 1000 + 7;
const double EPS = 1e-9;
int bit_count(int first) {
  return first == 0 ? 0 : 1 + bit_count(first & (first - 1));
}
inline int last_bit(int first) { return first & -first; }
inline int sign(double first) {
  return first < -EPS ? -1 : first > EPS ? 1 : 0;
}
inline int sign(int first) { return (first > 0) - (first < 0); }
int nextComb(int first) {
  if (!first) return (1 << 31) - 1;
  int smallest = first & -first;
  int ripple = first + smallest;
  int ones = first ^ ripple;
  ones = (ones >> 2) / smallest;
  return ripple | ones;
}
int gcd(int a, int b) {
  while (b) {
    int r = a % b;
    a = b;
    b = r;
  }
  return a;
}
int lcm(int a, int b) { return a / gcd(a, b) * b; }
struct UnionFind {
  vector<int> P, S, R;
  UnionFind(int n)
      : P(vector<int>(n)), S(vector<int>(n, 1)), R(vector<int>(n, 1)) {
    for (int i = (int)0; i < (int)n; ++i) P[i] = i;
  }
  int findP(int first) {
    if (P[first] != first) P[first] = findP(P[first]);
    return P[first];
  }
  inline int operator[](const int first) { return findP(first); }
  int merge(int a, int b) {
    int pa = findP(a), push_back = findP(b);
    if (pa == push_back) return 0;
    if (R[pa] < R[push_back]) {
      P[pa] = push_back;
      S[push_back] += S[pa];
    } else {
      P[push_back] = pa;
      S[pa] += S[push_back];
    }
    if (R[pa] == R[push_back]) ++R[pa];
    return 1;
  }
};
const int BUF_SIZE = 201;
char buf[BUF_SIZE];
inline string getToken() {
  scanf("%s", buf);
  return buf;
}
inline string getLine() {
  fgets(buf, BUF_SIZE, stdin);
  return buf;
}
inline int getInt() {
  int a;
  scanf("%d", &a);
  return a;
}
inline double getDouble() {
  double a;
  scanf("%lf", &a);
  return a;
}
inline int stoi(string first) {
  stringstream ss;
  int ret;
  ss << first;
  ss >> ret;
  return ret;
}
inline vector<string> split(string &s) {
  stringstream ss;
  ss << s;
  string t;
  vector<string> ret;
  while (ss >> t) ret.push_back(t);
  return ret;
}
template <class K, class V>
vector<K> getKeys(map<K, V> m) {
  vector<K> keys;
  for (typeof((m).begin()) it = (m).begin(); it != (m).end(); ++it)
    keys.push_back(it->first);
  return keys;
}
inline double myRand() {
  return ((double)rand() / RAND_MAX) + ((double)rand() / RAND_MAX / RAND_MAX);
}
const int X = 40;
long long dp[X][X];
void myCode() {
  int N = getInt(), H = getInt();
  for (int i = (int)0; i < (int)N; ++i)
    for (int j = (int)0; j < (int)N; ++j) dp[i][j] = 0;
  dp[0][0] = 1;
  for (int i = (int)1; i < (int)N + 1; ++i)
    for (int j = (int)i; j < (int)N + 1; ++j) {
      for (int k = (int)0; k < (int)i; ++k) {
        int first = j - i;
        if (k < 20) first = min(first, (1 << k) - 1);
        for (int t = (int)k; t < (int)first + 1; ++t)
          dp[i][j] += dp[i - 1][j - 1 - t] * dp[k][t] * (k == i - 1 ? 1 : 2);
      }
    }
  long long ret = 0;
  for (int i = (int)H; i < (int)N + 1; ++i) ret += dp[i][N];
  cout << ret << endl;
}
int main() {
  srand(0);
  myCode();
  return 0;
}
