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

#include <iostream>
#include <map>
#include <utility>

using namespace std;

int inf = 99999;

int vals[] = {10, 50, 100, 500};

int minuses[4];

void solve(int total, int n[4], int i, int uses[4], int *mincost) {
  if (i == 4) {
    int paysum = 0;
    int cost = 0;
    for (int j = 0; j < 4; ++j) {
      paysum += uses[j] * vals[j];
      cost -= uses[j];
    }
    int returns = paysum - total;
    if (returns < 0)
      return;

    for (int k = 3; k >= 0; --k) {
      int nret = returns / vals[k];
      returns %= vals[k];
      cost += nret;
    }

    if (cost < *mincost) {
      *mincost = cost;
      for (int k = 0; k < 4; ++k) {
        minuses[k] = uses[k];
      }
    }

    return;
  }

  for (int k = 0; k <= n[i]; ++k) {
    uses[i] = k;
    solve(total, n, i + 1, uses, mincost);
  }
}

int main() {
  bool found = false;
  while (1) {
    int total;
    int n[4];

    cin >> total;
    if (total == 0)
      break;

    cin >> n[0] >> n[1] >> n[2] >> n[3];

    int uses[4] = {0, 0, 0, 0};

    for (int i = 0; i < 4; ++i) {
      minuses[i] = 0;
    }
    int mincost = 9999;

    solve(total, n, 0, uses, &mincost);

    if (found) {
      cout << endl;
    }
    for (int i = 0; i < 4; ++i) {
      if (minuses[i]) {
        cout << vals[i] << " " << minuses[i] << endl;
      }
    }
    found = true;
  }
}

Error: TLE

Fixed submission:

#include <iostream>
#include <map>
#include <utility>

using namespace std;

int inf = 99999;

int vals[] = {500, 100, 50, 10};

int return_cost(int total, map<int, int> &payment) {
  int total_payment = 0;
  int cost = 0;
  for (map<int, int>::iterator it = payment.begin(); it != payment.end();
       ++it) {
    total_payment += it->first * it->second;
    cost -= it->second;
  }
  // cerr << "TOT " << total_payment << endl;
  int returns = total_payment - total;
  if (returns < 0) {
    return inf;
  }

  for (size_t i = 0; i < 4; ++i) {
    cost += int(returns / vals[i]);
    returns %= vals[i];
  }

  return cost;
}

pair<map<int, int>, int> find_payment(int total, map<int, int> &n, int i,
                                      map<int, int> &sofar) {
  if (i >= 4) {
    return make_pair(sofar, return_cost(total, sofar));
  }

  int val = vals[i];

  map<int, int> min_pays;
  int min_cost = inf;
  for (int k = 0; k <= n[val]; ++k) {
    map<int, int> pays(sofar);
    pays[val] = k;

    pair<map<int, int>, int> pa = find_payment(total, n, i + 1, pays);
    map<int, int> pays_ = pa.first;
    int cost = pa.second;
    if (cost < min_cost) {
      min_pays = pays_;
      min_cost = cost;
    }
  }

  return make_pair(min_pays, min_cost);
}

void solve(int total, map<int, int> &n) {
  map<int, int> sofar;
  pair<map<int, int>, int> pa = find_payment(total, n, 0, sofar);
  map<int, int> pays = pa.first;
  for (int i = 3; i >= 0; --i) {
    int val = vals[i];
    if (pays[val] > 0) {
      cout << val << " " << pays[val] << endl;
    }
  }
  cout << endl;
}

int main() {
  while (1) {
    int total;
    map<int, int> n;

    cin >> total;
    if (total == 0)
      break;

    cin >> n[10] >> n[50] >> n[100] >> n[500];
    solve(total, n);
  }
}