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

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
#include <string>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

struct Info {
  Info(int arg_num_500, int arg_kozeni) {
    num_500 = arg_num_500;
    kozeni = arg_kozeni;
  }

  int num_500, kozeni;
};

int N, max_kozeni[101], max_500, next_max_500, next_max_kozeni[101];
int **dp;
int **next_dp;

void func() {

  int P;
  max_500 = 0;
  for (int i = 0; i <= N; i++) {
    max_kozeni[i] = 0;
  }

  for (int i = 0; i <= N; i++) {
    for (int k = 0; k <= 500 * N; k++) {
      dp[i][k] = BIG_NUM;
      next_dp[i][k] = BIG_NUM;
    }
  }

  vector<Info> Updated;

  dp[0][0] = 0;
  next_dp[0][0] = 0;

  for (int loop = 0; loop < N; loop++) {
    scanf("%d", &P);
    next_max_500 = max_500;

    for (int i = 0; i <= N; i++) {
      next_max_kozeni[i] = max_kozeni[i];
    }

    for (int num_500 = 0; num_500 <= max_500; num_500++) {

      for (int kozeni = 0; kozeni <= max_kozeni[num_500]; kozeni++) {
        if (dp[num_500][kozeni] == BIG_NUM)
          continue;

        if (P % 1000 == 0) {

          if (kozeni >= 500) {
            next_max_500 = max(next_max_500, num_500 + 1);
            int next_kozeni = kozeni - 500;

            if (next_dp[num_500 + 1][next_kozeni] > dp[num_500][kozeni] + P) {
              next_dp[num_500 + 1][next_kozeni] = dp[num_500][kozeni] + P;
              Updated.push_back(Info(num_500 + 1, next_kozeni));
              next_max_kozeni[num_500 + 1] =
                  max(next_max_kozeni[num_500 + 1], next_kozeni);
            }
          }

        } else {

          int otsuri = 1000 * ((P / 1000) + 1) - P;

          if (otsuri >= 500) {
            next_max_500 = max(next_max_500, num_500 + 1);
            int next_kozeni = (otsuri - 500) + kozeni;
            if (next_dp[num_500 + 1][next_kozeni] > dp[num_500][kozeni] + P) {
              next_dp[num_500 + 1][next_kozeni] = dp[num_500][kozeni] + P;
              Updated.push_back(Info(num_500 + 1, next_kozeni));
              next_max_kozeni[num_500 + 1] =
                  max(next_max_kozeni[num_500 + 1], next_kozeni);
            }

          } else {

            if (next_dp[num_500][kozeni + otsuri] > dp[num_500][kozeni] + P) {
              next_dp[num_500][kozeni + otsuri] = dp[num_500][kozeni] + P;
              Updated.push_back(Info(num_500, kozeni + otsuri));
              next_max_kozeni[num_500] =
                  max(next_max_kozeni[num_500], kozeni + otsuri);
            }

            if (otsuri + kozeni >= 500) {
              next_max_500 = max(next_max_500, num_500 + 1);
              int next_kozeni = otsuri + kozeni - 500;
              if (next_dp[num_500 + 1][next_kozeni] > dp[num_500][kozeni] + P) {
                next_dp[num_500 + 1][next_kozeni] = dp[num_500][kozeni] + P;
                Updated.push_back(Info(num_500 + 1, next_kozeni));
                next_max_kozeni[num_500 + 1] =
                    max(next_max_kozeni[num_500 + 1], next_kozeni);
              }
            }
          }
        }
      }
    }

    for (int i = 0; i < Updated.size(); i++) {
      dp[Updated[i].num_500][Updated[i].kozeni] =
          next_dp[Updated[i].num_500][Updated[i].kozeni];
    }
    Updated.clear();

    for (int i = 0; i <= N; i++) {
      max_kozeni[i] = next_max_kozeni[i];
    }

    max_500 = next_max_500;
  }

  int minimum = BIG_NUM;
  for (int i = 0; i <= max_kozeni[max_500]; i++) {
    minimum = min(minimum, dp[max_500][i]);
  }

  printf("%d %d\\n", max_500, minimum);
}

int main() {

  dp = new int *[101];
  next_dp = new int *[101];

  for (int i = 0; i <= 100; i++) {
    dp[i] = new int[50001];
    next_dp[i] = new int[50001];
  }

  while (true) {
    scanf("%d", &N);
    if (N == 0)
      break;

    func();
  }

  return 0;
}

Error: 0

Fixed submission:

#include <algorithm>
#include <cfloat>
#include <cmath>
#include <iostream>
#include <queue>
#include <stack>
#include <stdio.h>
#include <string>
#include <vector>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;

struct Info {
  Info(int arg_num_500, int arg_kozeni) {
    num_500 = arg_num_500;
    kozeni = arg_kozeni;
  }

  int num_500, kozeni;
};

int N, max_kozeni[101], max_500, next_max_500, next_max_kozeni[101];
int **dp;
int **next_dp;

void func() {

  int P;
  max_500 = 0;
  for (int i = 0; i <= N; i++) {
    max_kozeni[i] = 0;
  }

  for (int i = 0; i <= N; i++) {
    for (int k = 0; k <= 1000 * N; k++) {
      dp[i][k] = BIG_NUM;
      next_dp[i][k] = BIG_NUM;
    }
  }

  vector<Info> Updated;

  dp[0][0] = 0;
  next_dp[0][0] = 0;

  for (int loop = 0; loop < N; loop++) {
    scanf("%d", &P);
    next_max_500 = max_500;

    for (int num_500 = 0; num_500 <= max_500; num_500++) {

      for (int i = 0; i <= N; i++) {
        next_max_kozeni[i] = max_kozeni[i];
      }

      for (int kozeni = 0; kozeni <= max_kozeni[num_500]; kozeni++) {
        if (dp[num_500][kozeni] == BIG_NUM)
          continue;

        if (P % 1000 == 0) {

          if (kozeni >= 500) {
            next_max_500 = max(next_max_500, num_500 + 1);
            int next_kozeni = kozeni - 500;

            if (dp[num_500 + 1][next_kozeni] > dp[num_500][kozeni] + P) {
              if (next_dp[num_500 + 1][next_kozeni] > dp[num_500][kozeni] + P) {
                next_dp[num_500 + 1][next_kozeni] = dp[num_500][kozeni] + P;
                Updated.push_back(Info(num_500 + 1, next_kozeni));
              }
            }

            next_max_kozeni[num_500 + 1] =
                max(next_max_kozeni[num_500 + 1], next_kozeni);
          }

        } else {

          int got_kozeni = 1000 * ((P / 1000) + 1) - P;

          next_max_kozeni[num_500] =
              max(next_max_kozeni[num_500], kozeni + got_kozeni);
          if (dp[num_500][kozeni + got_kozeni] > dp[num_500][kozeni] + P) {
            if (next_dp[num_500][kozeni + got_kozeni] >
                dp[num_500][kozeni] + P) {
              next_dp[num_500][kozeni + got_kozeni] = dp[num_500][kozeni] + P;
              Updated.push_back(Info(num_500, kozeni + got_kozeni));
            }
          }

          if (got_kozeni + kozeni >= 500) {
            next_max_500 = max(next_max_500, num_500 + 1);
            int next_kozeni = got_kozeni + kozeni - 500;
            if (dp[num_500 + 1][next_kozeni] > dp[num_500][kozeni] + P) {
              if (next_dp[num_500 + 1][next_kozeni] > dp[num_500][kozeni] + P) {
                next_dp[num_500 + 1][next_kozeni] = dp[num_500][kozeni] + P;
                Updated.push_back(Info(num_500 + 1, next_kozeni));
              }
            }
            next_max_kozeni[num_500 + 1] =
                max(next_max_kozeni[num_500 + 1], next_kozeni);
          }
        }
      }
    }

    for (int i = 0; i < Updated.size(); i++) {
      dp[Updated[i].num_500][Updated[i].kozeni] =
          next_dp[Updated[i].num_500][Updated[i].kozeni];
    }
    Updated.clear();

    for (int i = 0; i <= N; i++) {
      max_kozeni[i] = next_max_kozeni[i];
    }

    max_500 = next_max_500;
  }

  int minimum = BIG_NUM;
  for (int i = 0; i <= max_kozeni[max_500]; i++) {
    minimum = min(minimum, dp[max_500][i]);
  }

  printf("%d %d\\n", max_500, minimum);
}

int main() {

  dp = new int *[101];
  next_dp = new int *[101];

  for (int i = 0; i <= 100; i++) {
    dp[i] = new int[50001];
    next_dp[i] = new int[50001];
  }

  while (true) {
    scanf("%d", &N);
    if (N == 0)
      break;

    func();
  }

  return 0;
}