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

#include <bits/stdc++.h>
using namespace std;

#define INF 0x33433433

int n;
int rmin;
int rmax;
int rsum;
int wsum;
int r[114514];
int w[114514];
bool G[114514];

void SubsetSum(int N, int *as, int n) {
  int maxsum = 1000;
  int sum = 0;

  fill(G, G + N + 1, false);
  G[0] = true;
  for (int i = 1; i <= n; i++) {
    int lim = max(min(maxsum, N - as[i]), 1000);
    for (int j = lim; j >= lim - 1000; j--) {
      G[j + as[i]] |= G[j];
    }
    sum += as[i];
    maxsum = max(maxsum, sum);
  }
}

int main() {
  while (1) {
    scanf("%d", &n);
    if (n == 0)
      return 0;

    rsum = 0;
    wsum = 0;
    rmax = -1;
    rmin = INF;
    for (int i = 1; i <= n; i++) {
      scanf("%d%d", &r[i], &w[i]);
      rsum += r[i];
      wsum += w[i];
      rmax = max(rmax, r[i]);
      rmin = min(rmin, r[i]);
    }

    /*if (n > 3) {
      printf("%d\\n", rsum+wsum);
      continue;
    }*/

    int leftover;
    if (rmax >= rsum / 2 + rsum % 2) {
      leftover = rmax * 2 - rsum;
    } else {
      if (rmin < rsum / 3 + (rsum % 3 != 0)) {
        printf("%d\\n", rsum + wsum);
        continue;
      }

      assert(rsum % 3 == 0); // r = 0 mod 3 if the program reaches here
      leftover = rsum / 3;
    }

    bool should_move = false; // remove w[i] from w if r[i] == rmax
    for (int i = 1; i <= n; i++) {
      if (r[i] == rmax)
        should_move = true;
      if (should_move) {
        r[i] = r[i + 1];
        w[i] = w[i + 1];
      }
    }

    // printf("wsum: %d\\n", wsum);
    // printf("rsum: %d\\n", rsum);
    // printf("rmax: %d\\n", rmax);
    // printf("leftover: %d\\n", leftover);
    SubsetSum(leftover, w, n - 1); // put wi as many as possible
    int ans = -1;
    for (int i = leftover; i >= 0; i--) {
      if (G[i]) {
        // printf("i: %d\\n", i);
        ans = rsum + wsum + leftover - i;
        break;
      }
    }
    assert(ans != -1);
    printf("%d\\n", ans);
  }
}

Error: 0

Fixed submission:

#include <bits/stdc++.h>
using namespace std;

#define INF 0x33433433

int n;
int rmin;
int rmax;
int rsum;
int wsum;
int r[114514];
int w[114514];
bool G[114514];

void SubsetSum(int N, int *as, int n) {
  int maxsum = 1000;
  int sum = 0;

  fill(G, G + N + 1, false);
  G[0] = true;
  for (int i = 1; i <= n; i++) {
    int lim = max(min(maxsum, N - as[i]), 0);
    for (int j = lim; j >= lim - 1000; j--) {
      G[j + as[i]] |= G[j];
    }
    sum += as[i];
    maxsum = max(maxsum, sum);
  }
}

int main() {
  while (1) {
    scanf("%d", &n);
    if (n == 0)
      return 0;

    rsum = 0;
    wsum = 0;
    rmax = -1;
    rmin = INF;
    for (int i = 1; i <= n; i++) {
      scanf("%d%d", &r[i], &w[i]);
      rsum += r[i];
      wsum += w[i];
      rmax = max(rmax, r[i]);
      rmin = min(rmin, r[i]);
    }

    /*if (n > 3) {
      printf("%d\\n", rsum+wsum);
      continue;
    }*/

    int leftover;
    if (rmax >= rsum / 2 + rsum % 2) {
      leftover = rmax * 2 - rsum;
    } else {
      if (rmin < rsum / 3 + (rsum % 3 != 0)) {
        printf("%d\\n", rsum + wsum);
        continue;
      }

      assert(rsum % 3 == 0); // r = 0 mod 3 if the program reaches here
      leftover = rsum / 3;
    }

    bool should_move = false; // remove w[i] from w if r[i] == rmax
    for (int i = 1; i <= n; i++) {
      if (r[i] == rmax)
        should_move = true;
      if (should_move) {
        r[i] = r[i + 1];
        w[i] = w[i + 1];
      }
    }

    // printf("wsum: %d\\n", wsum);
    // printf("rsum: %d\\n", rsum);
    // printf("rmax: %d\\n", rmax);
    // printf("leftover: %d\\n", leftover);
    SubsetSum(leftover, w, n - 1); // put wi as many as possible
    int ans = -1;
    for (int i = leftover; i >= 0; i--) {
      if (G[i]) {
        // printf("i: %d\\n", i);
        ans = rsum + wsum + leftover - i;
        break;
      }
    }
    assert(ans != -1);
    printf("%d\\n", ans);
  }
}