Problem p02586 (C++) — buggy submission, verdict: Time Limit Exceeded

// AUTHOR: RAVAN_2070
// PUNE INSTITUTE OF COMPUTER TECHNOLOGY
/*
      I ♥ CLARICE STARLING...
        EXPLAINATION BELOW->
        2D DP
*/
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<pair<ll, ll>> vii;
typedef pair<ll, ll> pii;
typedef map<ll, ll> mii;
#define MOD7 1000000007
#define MOD9 1000000009
#define pi 3.1415926535
#define Test_cases                                                             \\
  ll TC;                                                                       \\
  cin >> TC;                                                                   \\
  while (TC--)
#define fastio                                                                 \\
  ios_base::sync_with_stdio(0);                                                \\
  cin.tie(0);                                                                  \\
  cout.tie(0);
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sp(x) fixed << setprecision(x)
#define sz(x) (ll)(x.size())
#define fo(i, a, b) for (i = a; i < b; i++)
#define foe(i, a, b) for (i = a; i <= b; i++)
const ll INF = (ll)2e18 + 77;
const int N = (int)3e3 + 1;
int M[N][N];
ll dp[N][N][4];
int r, c, k;
ll ans;
// dp[i][j][k]-->Represents max possible sum when we start from i,j and have
// already chosen k ekements in ith row
ll recursion(int i, int j, int k) {
  if (i >= r || j >= c)
    return 0ll;
  if (dp[i][j][k] != -1)
    return dp[i][j][k];
  dp[i][j][k] = 0;
  if (M[i][j] > 0 && k <= 2) {
    dp[i][j][k] =
        M[i][j] + max(recursion(i, j + 1, k + 1), recursion(i + 1, j, 0));
    dp[i][j][k] =
        max(dp[i][j][k], max(recursion(i, j + 1, k), recursion(i + 1, j, 0)));
  } else {
    dp[i][j][k] = max(recursion(i, j + 1, k), recursion(i + 1, j, 0));
  }
  return dp[i][j][k];
}
ll completeSearch(int i, int j, vector<int> &row) {
  ll sum = 0;
  // if(i==r-1&&j==c-1)ans=max(ans,sum),cout<<sum<<"\\n";
  if (M[i][j] > 0 && row[i] < 3) {
    ll a, b, c1, d1;
    a = b = c1 = d1 = 0ll;
    row[i]++;
    a = b = M[i][j];
    if (i + 1 < r)
      a += completeSearch(i + 1, j, row);
    if (j + 1 < c)
      b += completeSearch(i, j + 1, row);

    row[i]--;
    if (i + 1 < r)
      c1 = completeSearch(i + 1, j, row);
    if (j + 1 < c)
      d1 = completeSearch(i, j + 1, row);
    // cout<<i<<" "<<j<<"\\n";
    //  cout<<a<<" "<<b<<" "<<c1<<" "<<d1<<"\\n";
    sum = max(sum, a);
    sum = max(sum, b);
    sum = max(sum, c1);
    sum = max(sum, d1);
  } else {
    ll c1, d1;
    c1 = d1 = 0ll;
    if (i + 1 < r)
      c1 = completeSearch(i + 1, j, row);
    if (j + 1 < c)
      d1 = completeSearch(i, j + 1, row);
    sum = max(c1, d1);
  }
  return sum;
}
void solve() {
  cin >> r >> c >> k;
  int i, j, r1, c1, v1;
  fo(i, 0, k) {
    cin >> r1 >> c1 >> v1;
    r1--;
    c1--;
    M[r1][c1] = v1;
  }
  /*fo(i,0,r)
  {
      fo(j,0,c)
      {
          cout<<M[i][j]<<" ";
      }
      cout<<"\\n";
  }*/
  memset(dp, -1, sizeof dp);
  vector<int> row(r, 0ll);
  recursion(0, 0, 0);
  cout << dp[0][0][0] << "\\n";
}
int main() {
  fastio
  // Test_cases
  solve();
  return 0;
}
//**always check if you are not killing input in between
// map<ll,ll,greater<int>> to sort in descending order ,in iterator declaration
// no greater<int> if you want to apply lowerbound on set use
// s.lower_bound(key),not the one used for vector
// Syntax to create a min heap for priority queue priority_queue <int,
// vector<int>, greater<int>>;
// for modinverse use modularexponention(x,M-2,M);
// for "each" subtraction from ans(ans-k) if(ans<0) do ans+=MOD,ans%=MOD
// vector<vector<int>>dp(201,vector<int>(n+1)); A way to initialize vector of
// vector string2=string1.substr(pos,length);if len no specified then till end
// void fill (ForwardIterator first, ForwardIterator last, const T& val);
// The range filled is [first,last), which contains all the elements between
// first and last, including the element pointed by first but not the element
// pointed by last.

// If wrong on pretest 2 means logically wrong
/* TIPS FOR DEBUGGING
 * Check if values are not overflowing (use long long where required)
 * Check if ranges are inclusive or not.
 * Check properly if greedy will work or not before using it.
 * Check EDGE CASES!! Seriously, even in 2B, saving 8 points by being
 * 2 minutes faster will bite you in the ass if you don't make sure
 * it works on edge cases.
 * Keep adding to this list.
 */


Error: TLE

Fixed submission:

// AUTHOR: RAVAN_2070
// PUNE INSTITUTE OF COMPUTER TECHNOLOGY
/*
      I ♥ CLARICE STARLING...
        EXPLAINATION BELOW->
        2D DP
*/
#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long int ull;
typedef long long int ll;
typedef long double ld;
typedef vector<ll> vi;
typedef vector<pair<ll, ll>> vii;
typedef pair<ll, ll> pii;
typedef map<ll, ll> mii;
#define MOD7 1000000007
#define MOD9 1000000009
#define pi 3.1415926535
#define Test_cases                                                             \\
  ll TC;                                                                       \\
  cin >> TC;                                                                   \\
  while (TC--)
#define fastio                                                                 \\
  ios_base::sync_with_stdio(0);                                                \\
  cin.tie(0);                                                                  \\
  cout.tie(0);
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define lb lower_bound
#define ub upper_bound
#define all(x) x.begin(), x.end()
#define rall(x) x.rbegin(), x.rend()
#define sp(x) fixed << setprecision(x)
#define sz(x) (ll)(x.size())
#define fo(i, a, b) for (i = a; i < b; i++)
#define foe(i, a, b) for (i = a; i <= b; i++)
const ll INF = (ll)2e18 + 77;
const int N = (int)3e3 + 1;
int M[N][N];
ll dp[N][N][4];
int r, c, k;
ll ans;
// dp[i][j][k]-->Represents max possible sum when we start from i,j and have
// already chosen k ekements in ith row
ll recursion(int i, int j, int k) {
  if (i >= r || j >= c)
    return 0ll;
  if (dp[i][j][k])
    return dp[i][j][k];
  if (M[i][j] > 0 && k <= 2) {
    dp[i][j][k] =
        M[i][j] + max(recursion(i, j + 1, k + 1), recursion(i + 1, j, 0));
    dp[i][j][k] =
        max(dp[i][j][k], max(recursion(i, j + 1, k), recursion(i + 1, j, 0)));
  } else {
    dp[i][j][k] = max(recursion(i, j + 1, k), recursion(i + 1, j, 0));
  }
  return dp[i][j][k];
}
ll completeSearch(int i, int j, vector<int> &row) {
  ll sum = 0;
  // if(i==r-1&&j==c-1)ans=max(ans,sum),cout<<sum<<"\\n";
  if (M[i][j] > 0 && row[i] < 3) {
    ll a, b, c1, d1;
    a = b = c1 = d1 = 0ll;
    row[i]++;
    a = b = M[i][j];
    if (i + 1 < r)
      a += completeSearch(i + 1, j, row);
    if (j + 1 < c)
      b += completeSearch(i, j + 1, row);

    row[i]--;
    if (i + 1 < r)
      c1 = completeSearch(i + 1, j, row);
    if (j + 1 < c)
      d1 = completeSearch(i, j + 1, row);
    // cout<<i<<" "<<j<<"\\n";
    //  cout<<a<<" "<<b<<" "<<c1<<" "<<d1<<"\\n";
    sum = max(sum, a);
    sum = max(sum, b);
    sum = max(sum, c1);
    sum = max(sum, d1);
  } else {
    ll c1, d1;
    c1 = d1 = 0ll;
    if (i + 1 < r)
      c1 = completeSearch(i + 1, j, row);
    if (j + 1 < c)
      d1 = completeSearch(i, j + 1, row);
    sum = max(c1, d1);
  }
  return sum;
}
void solve() {
  cin >> r >> c >> k;
  int i, j, r1, c1, v1;
  fo(i, 0, k) {
    cin >> r1 >> c1 >> v1;
    r1--;
    c1--;
    M[r1][c1] = v1;
  }
  /*fo(i,0,r)
  {
      fo(j,0,c)
      {
          cout<<M[i][j]<<" ";
      }
      cout<<"\\n";
  }*/
  vector<int> row(r, 0ll);
  recursion(0, 0, 0);
  cout << dp[0][0][0] << "\\n";
}
int main() {
  fastio
  // Test_cases
  solve();
  return 0;
}
//**always check if you are not killing input in between
// map<ll,ll,greater<int>> to sort in descending order ,in iterator declaration
// no greater<int> if you want to apply lowerbound on set use
// s.lower_bound(key),not the one used for vector
// Syntax to create a min heap for priority queue priority_queue <int,
// vector<int>, greater<int>>;
// for modinverse use modularexponention(x,M-2,M);
// for "each" subtraction from ans(ans-k) if(ans<0) do ans+=MOD,ans%=MOD
// vector<vector<int>>dp(201,vector<int>(n+1)); A way to initialize vector of
// vector string2=string1.substr(pos,length);if len no specified then till end
// void fill (ForwardIterator first, ForwardIterator last, const T& val);
// The range filled is [first,last), which contains all the elements between
// first and last, including the element pointed by first but not the element
// pointed by last.

// If wrong on pretest 2 means logically wrong
/* TIPS FOR DEBUGGING
 * Check if values are not overflowing (use long long where required)
 * Check if ranges are inclusive or not.
 * Check properly if greedy will work or not before using it.
 * Check EDGE CASES!! Seriously, even in 2B, saving 8 points by being
 * 2 minutes faster will bite you in the ass if you don't make sure
 * it works on edge cases.
 * Keep adding to this list.
 */