Problem p03168 (C++)

Buggy submission (status: Time Limit Exceeded):
/*
      @author: Charan Sai
*/
#include <bits/stdc++.h>
using namespace std;

#define IOS                                                                    \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(0);                                                                  \
  cout.tie(0)
#define int long long
#define ppi pair<int, int>
#define endl "\n"
#define nl cout << "\n"
#define deb(x) cout << #x << " " << x << endl;

double head_prob[3000];
double dp[3000][3000];
int n;
// Base Case construction is really crucial
double Top_Down(int i, int heads) {
  // Base Case
  if (i == 0 && heads == 0)
    return 1;
  if (i == 0 && heads != 0)
    return 0;

  if (dp[i][heads] != 0)
    return dp[i][heads];

  // Choice
  if (heads == 0) {
    // Return prob of tail only
    return (dp[i][heads] = Top_Down(i - 1, heads) * (1 - head_prob[i]));
  } else if (i > heads) {
    return (dp[i][heads] = Top_Down(i - 1, heads - 1) * head_prob[i] +
                           Top_Down(i - 1, heads) * (1 - head_prob[i]));
  }

  return (dp[i][heads] = Top_Down(i - 1, heads - 1) * head_prob[i]);
}

void Bottom_Up() {
  dp[0][0] = 1;
  for (int j = 1; j <= n; ++j)
    dp[0][j] = 0;

  for (int i = 1; i <= n; ++i) {
    for (int heads = 0; heads <= n; ++heads) {
      if (heads == 0)
        dp[i][heads] = dp[i - 1][heads] * (1 - head_prob[i]);
      else if (i > heads) {
        dp[i][heads] = dp[i - 1][heads - 1] * head_prob[i] +
                       dp[i - 1][heads] * (1 - head_prob[i]);
      } else
        dp[i][heads] = dp[i - 1][heads - 1] * head_prob[i];
    }
  }

  double total_prob = 0.0;
  for (int heads = n / 2 + 1; heads <= n; ++heads) {
    total_prob += dp[n][heads];
  }

  cout << setprecision(10) << total_prob << endl;
}

int32_t main() {
  IOS;
  memset(dp, 0, sizeof(dp));
  cin >> n;
  for (int i = 1; i <= n; ++i) {
    cin >> head_prob[i];
  }
  double total_prob = 0.0;
  for (int heads = n / 2 + 1; heads <= n; ++heads) {
    // cout << Top_Down(n, heads);
    total_prob += Top_Down(n, heads);
  }
  Bottom_Up();
}

Fixed submission:
/*
      @author: Charan Sai
*/
#include <bits/stdc++.h>
using namespace std;

#define IOS                                                                    \
  ios_base::sync_with_stdio(false);                                            \
  cin.tie(0);                                                                  \
  cout.tie(0)
#define int long long
#define ppi pair<int, int>
#define endl "\n"
#define nl cout << "\n"
#define deb(x) cout << #x << " " << x << endl;

double head_prob[3000];
double dp[3000][3000];
int n;
// Base Case construction is really crucial
double Top_Down(int i, int heads) {
  // Base Case
  if (i == 0 && heads == 0)
    return 1;
  if (i == 0 && heads != 0)
    return 0;

  if (dp[i][heads] != 0)
    return dp[i][heads];

  // Choice
  if (heads == 0) {
    // Return prob of tail only
    return (dp[i][heads] = Top_Down(i - 1, heads) * (1 - head_prob[i]));
  } else if (i > heads) {
    return (dp[i][heads] = Top_Down(i - 1, heads - 1) * head_prob[i] +
                           Top_Down(i - 1, heads) * (1 - head_prob[i]));
  }

  return (dp[i][heads] = Top_Down(i - 1, heads - 1) * head_prob[i]);
}

void Bottom_Up() {
  dp[0][0] = 1;
  for (int j = 1; j <= n; ++j)
    dp[0][j] = 0;

  for (int i = 1; i <= n; ++i) {
    for (int heads = 0; heads <= n; ++heads) {
      if (heads == 0)
        dp[i][heads] = dp[i - 1][heads] * (1 - head_prob[i]);
      else if (i > heads) {
        dp[i][heads] = dp[i - 1][heads - 1] * head_prob[i] +
                       dp[i - 1][heads] * (1 - head_prob[i]);
      } else
        dp[i][heads] = dp[i - 1][heads - 1] * head_prob[i];
    }
  }

  double total_prob = 0.0;
  for (int heads = n / 2 + 1; heads <= n; ++heads) {
    total_prob += dp[n][heads];
  }

  cout << setprecision(10) << total_prob << endl;
}

int32_t main() {
  IOS;
  memset(dp, 0, sizeof(dp));
  cin >> n;
  for (int i = 1; i <= n; ++i) {
    cin >> head_prob[i];
  }
  Bottom_Up();
}