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

#include <cstdio>
#include <iostream>

using namespace std;

enum coins { ten = 0, fifty, hundred, five_hundred, coin_max };
const int kcoin[coin_max] = {10, 50, 100, 500};

int M;
int min_nums;
int ans_nums[coin_max];
int nums[coin_max];
int tans_nums[coin_max];

int minimumExchange(int m, int *nums) {
  int t = 0;
  int ans = 0;

  for (int i = five_hundred; i >= ten; --i) {
    t = m / kcoin[i];
    m -= kcoin[i] * t;
    nums[i] = t;
    ans += t;
  }

  return ans;
}

void solve() {
  for (int a = 0; a <= nums[ten]; ++a) {
    for (int b = 0; b <= nums[fifty]; ++b) {
      for (int c = 0; c <= nums[hundred]; ++c) {
        for (int d = 0; d <= nums[five_hundred]; ++d) {
          int m = a * kcoin[ten] + b * kcoin[fifty] + c * kcoin[hundred] +
                  d * kcoin[five_hundred];

          if (m >= M) {
            int t = 0;
            int exchanges[coin_max];

            nums[0] -= a;
            nums[1] -= b;
            nums[2] -= c;
            nums[3] -= d;
            tans_nums[0] += a;
            tans_nums[1] += b;
            tans_nums[2] += c;
            tans_nums[3] += d;

            minimumExchange(m - M, exchanges);

            for (int i = 0; i < coin_max; ++i) {
              t += nums[i] + exchanges[i];
            }

            if (min_nums > t) {
              min_nums = t;
              for (int i = 0; i < coin_max; ++i) {
                ans_nums[i] = tans_nums[i];
              }
            }

            tans_nums[0] -= a;
            tans_nums[1] -= b;
            tans_nums[2] -= c;
            tans_nums[3] -= d;
            nums[0] += a;
            nums[1] += b;
            nums[2] += c;
            nums[3] += d;
          }
        }
      }
    }
  }
}

int main() {
  bool bFirstDataSet = true;

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

    for (int i = 0; i < coin_max; ++i) {
      tans_nums[i] = ans_nums[i] = nums[i] = 0;
    }

    for (int i = 0; i < coin_max; ++i) {
      scanf("%d", nums + i);
    }

    if (!bFirstDataSet) {
      printf("\\n");
    }
    bFirstDataSet = false;

    min_nums = 100;
    solve();

    for (int i = 0; i < 4; ++i) {
      if (ans_nums[i]) {
        printf("%d %d\\n", kcoin[i], ans_nums[i]);
      }
    }
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <cstdio>
#include <iostream>

using namespace std;

enum coins { ten = 0, fifty, hundred, five_hundred, coin_max };
const int kcoin[coin_max] = {10, 50, 100, 500};

int min_nums;
int ans_nums[coin_max];
int nums[coin_max];
int tans_nums[coin_max];

void solve(int m) {
  if (m <= 0) {
    int t = 0;
    for (int c = 0; c < coin_max - 1; ++c) {
      switch (c) {
      case ten:
        if (nums[ten] >= 10) {
          nums[ten] -= 10;
          nums[hundred] += 1;
          tans_nums[ten] += 10;
          --c;
        }
        if (nums[ten] >= 5) {
          nums[ten] -= 5;
          nums[fifty] += 1;
          tans_nums[ten] += 5;
          --c;
        }
        break;
      case fifty:
        if (nums[fifty] >= 10) {
          nums[fifty] -= 10;
          nums[five_hundred] += 1;
          tans_nums[fifty] += 10;
          --c;
        }
        if (nums[fifty] >= 2) {
          nums[fifty] -= 2;
          nums[hundred] += 1;
          tans_nums[fifty] += 2;
          --c;
        }
        break;
      case hundred:
        if (nums[hundred] >= 5) {
          nums[hundred] -= 5;
          nums[five_hundred] += 1;
          tans_nums[hundred] += 5;
          --c;
        }
        break;
      }
    }
    for (int c = 0; c < coin_max; ++c) {
      t += nums[c];
    }
    if (min_nums > t) {
      min_nums = t;
      for (int c = 0; c < coin_max; ++c) {
        ans_nums[c] = tans_nums[c];
      }
    }
    return;
  }

  for (int i = 0; i < coin_max; ++i) {
    if (nums[i] == 0)
      continue;
    --nums[i];
    ++tans_nums[i];
    solve(m - kcoin[i]);
    ++nums[i];
    --tans_nums[i];
  }
}

int main() {
  bool bFirstDataSet = true;

  while (true) {
    int M;

    scanf("%d", &M);
    if (M == 0)
      break;

    min_nums = 100;
    for (int i = 0; i < coin_max; ++i) {
      tans_nums[i] = ans_nums[i] = 0;
    }

    for (int i = 0; i < coin_max; ++i) {
      scanf("%d", nums + i);
    }

    if (!bFirstDataSet)
      printf("\\n");
    bFirstDataSet = false;

    solve(M);

    for (int i = 0; i < 4; ++i) {
      if (ans_nums[i]) {
        printf("%d %d\\n", kcoin[i], ans_nums[i]);
      }
    }
  }

  return 0;
}