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

#include <limits.h>
#include <stdio.h>
#define LIM 667000
int P, C[6] = {1, 5, 10, 50, 100, 500};
int N[6], R[6], limit;
int clerk[LIM];
int i, j;

int getChange(int sum) { // clerk
  int ret = 0;
  int l;
  for (l = 5; l >= 0; l--) {
    if (sum >= C[l]) {
      ret += sum / C[l];
      sum -= sum / C[l] * C[l];
    }
  }
  return ret;
}

int getChangeBy(int sum) {
  int ret = 0;
  int index = sum;
  int e;
  for (e = 0; e < 6; e++)
    R[e] = 0;
  for (e = 5; e >= 0; e--) {
    if (sum >= C[e] && N[e] != 0) {
      R[e] = sum / C[e] > N[e] ? N[e] : sum / C[e];
      sum -= R[e] * C[e];
      ret += R[e];
    }
  }
  if (sum != 0)
    return -1;
  return ret;
}

void createChange() {
  for (i = 0; i < LIM; i++)
    clerk[i] = 0;
  int B, f;
  for (f = 1; f < 666001; f++) {
    B = getChange(f);
    clerk[f] = B;
    // if(f < 100)printf("%d\\n",clerk[f]);
  }
}

int main() {
  createChange();

  while (scanf("%d", &P) && P) {
    int cnt, pay, ans, res;

    limit = 0;
    int u;
    for (u = 0; u < 6; u++) {
      scanf("%d", &N[u]);

      limit += N[u] * C[u];
    }

    ans = INT_MAX;
    for (i = 0; i < limit; i++)
      clerk[i] = -1;
    for (i = P; i <= limit; i++) {
      cnt = getChangeBy(i);
      if (cnt == -1 || ans <= cnt)
        continue;
      pay = 0;
      for (j = 0; j < 6; j++)
        pay += C[j] * R[j];
      if (clerk[pay - P] == -1)
        clerk[pay - P] = getChange(pay - P);
      if (cnt + clerk[pay - P] < ans) {
        ans = cnt + clerk[pay - P];
      }
    }
    printf("%d\\n", ans);
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <climits>
#include <cstdio>
#include <iostream>
#include <vector>
#define LIM 667000
#define REP(i, s, n) for (int i = s; i < n; i++)
#define rep(i, n) REP(i, 0, n)
#define pb push_back
using namespace std;
int P, C[6] = {1, 5, 10, 50, 100, 500};
int N[6], R[6], limit;
int clerk[LIM];

bool input() {
  scanf("%d", &P);
  int br = P;
  limit = 0;
  rep(i, 6) {
    scanf("%d", &N[i]);
    br += N[i];
    limit += N[i] * C[i];
  }
  if (br == 0)
    return false;
  return true;
}

int getChange(int sum) { // clerk
  int ret = 0;
  for (int i = 5; i >= 0; i--) {
    if (sum >= C[i]) {
      ret += sum / C[i];
      sum -= sum / C[i] * C[i];
    }
  }
  return ret;
}

int getChangeBy(int sum) {
  int ret = 0;
  int index = sum;
  rep(i, 6) R[i] = 0;
  for (int i = 5; i >= 0; i--) {
    if (sum >= C[i] && N[i] != 0) {
      R[i] = min(sum / C[i], N[i]);
      sum -= R[i] * C[i], ret += R[i];
    }
  }
  if (sum != 0)
    return -1;
  return ret;
}

void createChange() {
  rep(i, LIM) clerk[i] = 0;

  REP(i, 1, 666500) {
    int B = getChange(i);
    clerk[i] = B;
  }
}

int main() {
  // createChange();

  while (true) {
    if (!input())
      break;
    int ans = INT_MAX;
    rep(i, limit) clerk[i] = -1;
    for (int i = P; i <= limit; i++) {
      int cnt = getChangeBy(i);
      if (cnt == -1 || ans <= cnt)
        continue;
      int pay = 0;
      rep(j, 6) pay += C[j] * R[j];
      if (clerk[pay - P] == -1)
        clerk[pay - P] = getChange(pay - P);
      if (cnt + clerk[pay - P] < ans) {
        ans = cnt + clerk[pay - P];
      }
    }
    printf("%d\\n", ans);
  }
  return 0;
}