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

#include <stdio.h>
int min(int a, int b) { return a > b ? b : a; }
struct man {
  int pow;
  int wei;
  void in() {
    scanf("%d%d", &pow, &wei);
    return;
  }
  void operator=(man a) {
    pow = a.pow;
    wei = a.wei;
    return;
  }
  man carry(man a) {
    pow -= a.wei;
    wei += a.wei;
    pow = min(pow, a.pow);
    return *this;
  }
  void bebad() {
    pow = -2;
    return;
  }
  bool isbad() { return pow == -2; }
};
bool can(man a, man b) { return a.pow >= b.wei; }
man max(man a, man b) { return a.pow > b.pow ? a : b; }
int max(int a, int b) { return a > b ? a : b; }
bool better(man a, man b) { return a.pow > b.pow; }
const int N = 1e3 + 10;
int main() {
  int n, val[N][N], h[N][N];
  man a[N][N], l, r;
  scanf("%d", &n);
  for (int i = 1; i <= n; i++) {
    a[i][i].in();
    h[i][i] = i;
    val[i][i] = 1;
  }
  for (int j = 1; j < n; j++) {
    l = a[j][j];
    r = a[j + 1][j + 1];
    h[j][j + 1] = j;

    if (can(l, r)) {
      if (can(r, l))
        a[j][j + 1] = max(l.carry(a[j + 1][j + 1]), r.carry(a[j][j]));
      else
        a[j][j + 1] = l.carry(r);
      val[j][j + 1] = 1;
    } else if (can(r, l)) {
      a[j][j + 1] = r.carry(l);
      val[j][j + 1] = 1;
    } else {
      val[j][j + 1] = 2;
      a[j][j + 1].bebad();
    }
  }
  for (int i = 2; i < n; i++) {
    for (int j = 1; j <= n - i; j++) {
      h[j][j + i] = h[j][j + i - 1];
      l = a[j][j];
      r = a[j + 1][j + i];
      val[j][j + i] = i + 1;
      if (r.isbad()) {
        val[j][j + i] = val[j][j] + val[j + 1][j + i];
        a[j][j + i].bebad();
      } else {
        if (can(l, r)) {
          a[j][j + i] = l.carry(r);
          val[j][j + i] = 1;
        } else {
          val[j][j + i] = 2;
          a[j][j + i].bebad();
        }
      }
      l = a[j][j + i - 1];
      r = a[j + i][j + i];
      if (l.isbad()) {
        if (val[j][j + i] > val[j][j + i - 1] + val[j + i][j + i]) {
          val[j][j + i] = val[j][j + i - 1] + val[j + i][j + i];
          a[j][j + i].bebad();
        }
      } else {
        if (can(r, l)) {
          if (val[j][j + i] > 1) {
            val[j][j + i] = 1;
            h[j][j + i] = j + i - 1;
            a[j][j + i] = r.carry(l);
          } else if (val[j][j + i] == 1 && better(r.carry(l), a[j][j + i])) {
            h[j][j + i] = j + i - 1;
            a[j][j + i] = r;
          }

        } else {
          if (val[j][j + i] > 2) {
            val[j][j + i] = 2;
            h[j][j + i] = j + i - 1;
            a[j][j + i].bebad();
          }
        }
      }
      for (int k = max(h[j][j + i - 1] - 10, j);
           k <= h[j + 1][j + i] && k < j + i; k++) {
        if (val[j][k] + val[k + 1][j + i] < val[j][j + i]) {
          val[j][j + i] = val[j][k] + val[k + 1][j + i];
          a[j][j + i].bebad();
          h[j][j + i] = k;
        }
      }
      // printf("val[%d][%d]=%d\\n",j,j+i,val[j][j+i]);
    }
  }
  // for(int i=1;i<=n;i++)for(int
  // j=i;j<=n;j++)printf("val[%d][%d]=%d\\n",i,j,val[i][j]);
  printf("%d\\n", val[1][n]);
}
/*val[1][1]=0
val[1][2]=1
val[1][3]=1
val[1][4]=2
val[1][5]=2
val[1][6]=2
val[1][7]=3
val[2][2]=0
val[2][3]=1
val[2][4]=2
val[2][5]=2
val[2][6]=2
val[2][7]=3
val[3][3]=1
val[3][4]=1
val[3][5]=1
val[3][6]=1
val[3][7]=2
val[4][4]=1
val[4][5]=1
val[4][6]=1
val[4][7]=2
val[5][5]=1
val[5][6]=1
val[5][7]=1
val[6][6]=1
val[6][7]=1
val[7][7]=1*/


Error: TLE

Fixed submission:

#pragma GCC optimize("Ofast")
#include <stdio.h>
int min(int a, int b) { return a > b ? b : a; }
struct man {
  int wei;
  int pow;
  void in() {
    scanf("%d%d", &pow, &wei);
    return;
  }
  void carry(man a) {
    wei += a.wei;
    pow -= a.wei;
    pow = min(pow, a.pow);
    return;
  }
  void operator=(man a) {
    wei = a.wei;
    pow = a.pow;
    return;
  }
  void bad() {
    pow = wei = -2;
    return;
  }
  bool used() { return wei != 0; }
  bool cant() { return pow == -2; }
};
man better(man a, man b) { return a.pow > b.pow ? a : b; }
bool can(man a, man b) { return a.pow >= b.wei; }
const int N = 1e3 + 10;
man a[N], ans[N][N];
int val[N][N];
man dp(int l, int r) {
  if (ans[l][r].used())
    return ans[l][r];
  if (l == r) {
    val[l][r] = 1;
    ans[l][r] = a[l];
  } else if (r - l == 1) {
    man b = a[l], c = a[r];
    if (can(a[l], a[r])) {
      b.carry(a[r]);
      if (can(a[r], a[l])) {
        c.carry(a[l]);
        b = better(b, c);
      }
      ans[l][r] = b;
      val[l][r] = 1;
    } else if (can(a[r], a[l])) {
      ans[l][r] = c;
      ans[l][r].carry(a[l]);
      val[l][r] = 1;
    } else {
      ans[l][r].bad();
      val[l][r] = 2;
    }
  } else {
    man b = a[l], c = dp(l + 1, r);
    val[l][r] = N;
    if (!c.cant()) {
      if (can(b, c)) {
        ans[l][r] = b;
        ans[l][r].carry(c);
        val[l][r] = 1;
      } else {
        ans[l][r].bad();
        val[l][r] = 2;
      }
    } else {
      ans[l][r].bad();
      val[l][r] = val[l + 1][r] + 1;
    }
    b = a[r], c = dp(l, r - 1);
    if (!c.cant()) {
      if (can(b, c)) {
        b.carry(c);
        ans[l][r] = better(ans[l][r], b);
        val[l][r] = 1;
      } else {
        if (val[l][r] > 2) {
          val[l][r] = 2;
          ans[l][r].bad();
        }
      }
    } else {
      if (val[l][r] > val[l][r - 1] + 1) {
        ans[l][r].bad();
        val[l][r] = val[l][r - 1] + 1;
      }
    }
    for (int i = l + 1; i < r; i++) {
      if (!ans[l][i].used())
        dp(l, i);
      if (!ans[i + 1][r].used())
        dp(i + 1, r);
      if (val[l][i] + val[i + 1][r] < val[l][r]) {
        val[l][r] = val[l][i] + val[i + 1][r];
        ans[l][r].bad();
      }
    }
  }
  return ans[l][r];
}
int main() {
  int n;
  scanf("%d", &n);
  for (int i = 0; i < n; i++)
    a[i].in();
  dp(0, n - 1);
  printf("%d\\n", val[0][n - 1]);
}