Problem p01088 (C++) — buggy submission, verdict: Runtime Error

/*
 * D.cpp
 *
 *  Created on: 2017/07/01
 *      Author: LitMc
 */

// #define MYDEBUG
#include <bits/stdc++.h>

#ifdef MYDEBUG
#define dbp(x) cout << #x << ": " << x << endl
#define dbp2(x, y) cout << #x << "," << #y << ": " << x << "," << y << endl
#define dbp3(x, y, z)                                                          \\
  cout << #x << "," << #y << "," << #z << ": " << x << "," << y << "," << z    \\
       << endl
#define dbp4(w, x, y, z)                                                       \\
  cout << #w << "," << #x << "," << #y << "," << #z << ": " << w << "," << x   \\
       << "," << y << "," << z << endl
#define ifcin(x) std::ifstream cin(x)
#else
#define dbp(x)
#define dbp2(x, y)
#define dbp3(x, y, z)
#define dbp4(w, x, y, z)
#define ifcin(x)
#endif
#define ll long long
#define ull unsigned long long
#define all(x) x.begin(), x.end()
#define rep(i, from, to) for (int i = from; i < to; ++i)
#define REP(i, from, to) for (int i = from; i <= to; ++i)
#define EPS = 1e-14;
using std::cin;
using std::cout;
using std::endl;
using std::fill;
using std::greater;
using std::max;
using std::min;
using std::ostream;
using std::pair;
using std::priority_queue;
using std::reverse;
using std::sort;
using std::string;
using std::swap;
using std::vector;

template <typename T>
ostream &operator<<(ostream &out, const vector<vector<T>> &v) {
  for (size_t i = 0; i < v.size(); ++i) {
    out << v[i] << endl;
  }
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << "[";
  size_t last = v.size() - 1;
  for (size_t i = 0; i < v.size(); ++i) {
    out << v[i];
    if (i != last) {
      out << ",";
    }
  }
  out << "]";
  return out;
}
typedef pair<int, int> P;
bool cmp(const P &p1, const P &p2) {
  if (p1.first == p2.first) {
    return p1.second > p2.second;
  } else {
    return p1.first < p2.first;
  }
}
static const int MAX_N = 102;
static const int MAX_E = 1000 * MAX_N; // 10^5
int n;
int p[MAX_N];
P dp[MAX_N][MAX_E];
// P ch[MAX_N][MAX_E]; //??????????????¨
// dp[i][k]:
// k????°?????????????????????¶?????§???i????????\\????????????????????£?????????????????????????????§???
// dp[1][0]: ?¬??????????
// dp[n+1][*]: ?????????(0???, 0???)

void init() {
  rep(i, 0, MAX_N) {
    p[i] = 0;
    rep(j, 0, MAX_E) { dp[i][j] = P(0, 0); }
  }
}

// ex: 900
// p: 400
// 1900?????????
// 1000 = (400+1000-1)/1000
// 900: ex
// 1900 - 400 = 1500
//%1000????????¨500, 1???get
//??????
// base: (p + 1000 - 1) / 1000 : 1000???????????§??????????????????
//?????????????????£????????¨?????????: ex
//????????????: base + ex
//????????????: ret = (base+ex) - p
//????????????500??????????????°: ret%1000
//?????????????????????: p
// 500????????????????????????????????£???: ret - ((ret%1000) / 500) * 500
// 100?????????????????????, ?°????700???
// 1000 + 700 - 100 = 1600
// 1600%1000 = 600
// 600/500 = 1
//?????£???: 1600 - 1*500 = 1100
// 1700????????£???+1100???(600???????????????)
//????±???????????????£????????????p???????????????????????????????????£????????????????????£?????????

//??????price??????1000???????????§???????????????????????????
int only1000(int &price) { return ((price + 1000 - 1) / 1000) * 1000; }

void doDP() {
  rep(k, 0, MAX_E) { dp[n + 1][k] = P(0, 0); }
  for (int i = n; i >= 1; --i) {
    int base = only1000(p[i]);
    int pay, ret, get; // get: 500??????????????????????????°(0???1)
    rep(ex, 0,
        MAX_E -
            1000) // 1??????1000?????\\???????°???????????????\\???????????¨?????????
    {
      P nobuy, buy1000, try500; //???????????§??????????????¢????????§??????3???(????????????,
                                //?°??????????, 500????????????)w
      //????????????
      nobuy = dp[i + 1][ex];
      //??????
      //    ?°?????????£???????????????
      pay = base;
      ret = pay - p[i];
      get = ret / 500;
      ret -= get * 500; // 500??????????????????????????????????¶??????????
      buy1000 =
          dp[i + 1][ret + ex]; //?°?????????????????????£????????§???????¶????
      buy1000.first += get;
      buy1000.second += p[i];
      //      int ret1000 = ret;
      //    500?????????????????????
      int usedEx = 0;
      pay = base;
      ret = pay - p[i];
      if (ret >= 500) { // 500??????????°?????????¢???????????????
        usedEx = 0;
        get = ret / 500;
        ret -= get * 500;
      } else if (ret + ex >=
                 500) { //?°???????????????°500?????????????????§??????
        usedEx = 500 - ret;
        pay += usedEx;
        ret = pay - p[i]; //??????500??????????????????
        get = ret / 500;
        ret -= get * 500;
      } else {
        // 1000???????????§?????£???????°????????????£??????500??????????????§?????????
        usedEx = 0;
      }
      try500 = dp[i + 1][ret + ex - usedEx];
      try500.first += get;
      try500.second += p[i];
      P best = max(buy1000, try500, cmp);
      best = max(best, nobuy, cmp);
      //      if (best == nobuy) {
      //        ch[i][ex] = P(i + 1, ex);
      //      } else if (best == buy1000) {
      //        ch[i][ex] = P(i + 1, ret1000);
      //      } else if (best == try500) {
      //        ch[i][ex] = P(i + 1, ret);
      //      }
      dp[i][ex] = best;
    }
  }
}

// void trace() {      //???????????????????????°??¨
//   int i = 1;
//   int ex = 0;
//   REP(t,1,4)
//   {
//     dbp4(i, ex, dp[i][ex].first, dp[i][ex].second);
//     P next = ch[i][ex];
//     i = next.first;
//     ex = next.second;
//   }
// }

void solve() {
  while (cin >> n, n) {
    init();
    REP(i, 1, n) { cin >> p[i]; }
    doDP();
    cout << dp[1][0].first << " " << dp[1][0].second << endl;
  }
}

int main() { solve(); }

Error: TLE

Fixed submission:

/*
 * D.cpp
 *
 *  Created on: 2017/07/01
 *      Author: LitMc
 */

#define MYDEBUG
#include <bits/stdc++.h>

#ifdef MYDEBUG
#define dbp(x) cout << #x << ": " << x << endl
#define dbp2(x, y) cout << #x << "," << #y << ": " << x << "," << y << endl
#define dbp3(x, y, z)                                                          \\
  cout << #x << "," << #y << "," << #z << ": " << x << "," << y << "," << z    \\
       << endl
#define dbp4(w, x, y, z)                                                       \\
  cout << #w << "," << #x << "," << #y << "," << #z << ": " << w << "," << x   \\
       << "," << y << "," << z << endl
#define ifcin(x) std::ifstream cin(x)
#else
#define dbp(x)
#define dbp2(x, y)
#define dbp3(x, y, z)
#define dbp4(w, x, y, z)
#define ifcin(x)
#endif
#define ll long long
#define ull unsigned long long
#define all(x) x.begin(), x.end()
#define rep(i, from, to) for (int i = from; i < to; ++i)
#define REP(i, from, to) for (int i = from; i <= to; ++i)
#define EPS = 1e-14;
using std::cin;
using std::cout;
using std::endl;
using std::fill;
using std::greater;
using std::max;
using std::min;
using std::ostream;
using std::pair;
using std::priority_queue;
using std::reverse;
using std::sort;
using std::string;
using std::swap;
using std::vector;

template <typename T>
ostream &operator<<(ostream &out, const vector<vector<T>> &v) {
  for (size_t i = 0; i < v.size(); ++i) {
    out << v[i] << endl;
  }
  return out;
}

template <typename T> ostream &operator<<(ostream &out, const vector<T> &v) {
  out << "[";
  size_t last = v.size() - 1;
  for (size_t i = 0; i < v.size(); ++i) {
    out << v[i];
    if (i != last) {
      out << ",";
    }
  }
  out << "]";
  return out;
}
typedef pair<int, int> P;
bool cmp(const P &p1, const P &p2) {
  if (p1.first == p2.first) {
    return p1.second > p2.second;
  } else {
    return p1.first < p2.first;
  }
}
static const int MAX_N = 102;
static const int MAX_E = 1000 * MAX_N; // 10^5
int n;
int p[MAX_N];
P dp[MAX_N][MAX_E];
// P ch[MAX_N][MAX_E]; //??????????????¨
// dp[i][k]:
// k????°?????????????????????¶?????§???i????????\\????????????????????£?????????????????????????????§???
// dp[1][0]: ?¬??????????
// dp[n+1][*]: ?????????(0???, 0???)

void init() {
  rep(i, 0, MAX_N) {
    p[i] = 0;
    rep(j, 0, MAX_E) { dp[i][j] = P(0, 0); }
  }
}

// ex: 900
// p: 400
// 1900?????????
// 1000 = (400+1000-1)/1000
// 900: ex
// 1900 - 400 = 1500
//%1000????????¨500, 1???get
//??????
// base: (p + 1000 - 1) / 1000 : 1000???????????§??????????????????
//?????????????????£????????¨?????????: ex
//????????????: base + ex
//????????????: ret = (base+ex) - p
//????????????500??????????????°: ret%1000
//?????????????????????: p
// 500????????????????????????????????£???: ret - ((ret%1000) / 500) * 500
// 100?????????????????????, ?°????700???
// 1000 + 700 - 100 = 1600
// 1600%1000 = 600
// 600/500 = 1
//?????£???: 1600 - 1*500 = 1100
// 1700????????£???+1100???(600???????????????)
//????±???????????????£????????????p???????????????????????????????????£????????????????????£?????????

//??????price??????1000???????????§???????????????????????????
int only1000(int &price) { return ((price + 1000 - 1) / 1000) * 1000; }

void doDP() {
  rep(k, 0, MAX_E) { dp[n + 1][k] = P(0, 0); }
  for (int i = n; i >= 1; --i) {
    int base = only1000(p[i]);
    int pay, ret, get; // get: 500??????????????????????????°(0???1)
    rep(ex, 0, MAX_E) {
      P nobuy, buy1000, try500; //???????????§??????????????¢????????§??????3???(????????????,
                                //?°??????????, 500????????????)w
      //????????????
      nobuy = dp[i + 1][ex];
      //??????
      //    ?°?????????£???????????????
      pay = base;
      ret = pay - p[i];
      get = ret / 500;
      ret -= get * 500; // 500??????????????????????????????????¶??????????
      buy1000 =
          dp[i + 1][ret + ex]; //?°?????????????????????£????????§???????¶????
      buy1000.first += get;
      buy1000.second += p[i];
      //      int ret1000 = ret;
      //    500?????????????????????
      int usedEx = 0;
      pay = base;
      ret = pay - p[i];
      if (ret >= 500) { // 500??????????°?????????¢???????????????
        usedEx = 0;
        get = ret / 500;
        ret -= get * 500;
      } else if (ret + ex >=
                 500) { //?°???????????????°500?????????????????§??????
        usedEx = 500 - ret;
        pay += usedEx;
        ret = pay - p[i]; //??????500??????????????????
        get = ret / 500;
        ret -= get * 500;
      } else {
        // 1000???????????§?????£???????°????????????£??????500??????????????§?????????
        usedEx = 0;
      }
      try500 = dp[i + 1][ret + ex - usedEx];
      try500.first += get;
      try500.second += p[i];
      P best = max(buy1000, try500, cmp);
      best = max(best, nobuy, cmp);
      //      if (best == nobuy) {
      //        ch[i][ex] = P(i + 1, ex);
      //      } else if (best == buy1000) {
      //        ch[i][ex] = P(i + 1, ret1000);
      //      } else if (best == try500) {
      //        ch[i][ex] = P(i + 1, ret);
      //      }
      dp[i][ex] = best;
    }
  }
}

// void trace() {      //????????????
//   int i = 1;
//   int ex = 0;
//   REP(t,1,4)
//   {
//     dbp4(i, ex, dp[i][ex].first, dp[i][ex].second);
//     P next = ch[i][ex];
//     i = next.first;
//     ex = next.second;
//   }
// }

void solve() {
  while (cin >> n, n) {
    init();
    REP(i, 1, n) { cin >> p[i]; }
    doDP();
    cout << dp[1][0].first << " " << dp[1][0].second << endl;
  }
}

int main() { solve(); }