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

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <utility>

using namespace std;

#define dump(n) cerr << "# " << #n << "=" << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define iter(c) __typeof__((c).begin())
#define foreach(i, c) for (iter(c) i = (c).begin(); i != (c).end(); ++i)
#define all(c) (c).begin(), (c).end()
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int, int> pii;

int res;

void solve(vi &hist, int i, int remain, int cur) {
  res = max(res, cur);
  if (i == 10)
    return;

  int x = 0;
  repi(j, 1, 10) x += hist[j] * j;
  if (cur + x / 10 < res)
    return;

  if (remain == 0) {
    remain = 10;
    cur++;
    i = 1;
  }

  solve(hist, i + 1, remain, cur);
  if (hist[i] > 0 && remain >= i) {
    hist[i]--;
    solve(hist, i, remain - i, cur);
    hist[i]++;
  }
}

int main() {
  for (int n; scanf("%d", &n), n;) {
    vi hist(10);
    rep(i, n) {
      int m;
      scanf("%d", &m);
      hist[m]++;
    }

    int sum = hist[5] / 2;
    hist[5] %= 2;
    repi(i, 1, 5) while (hist[i] && hist[10 - i]) {
      sum++;
      hist[i]--;
      hist[10 - i]--;
    }

    res = 0;
    solve(hist, 1, 10, 0);
    printf("%d\\n", res + sum);
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <bitset>
#include <cassert>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <utility>

using namespace std;

#define dump(n) cerr << "# " << #n << "=" << (n) << endl
#define repi(i, a, b) for (int i = int(a); i < int(b); i++)
#define peri(i, a, b) for (int i = int(b); i-- > int(a);)
#define rep(i, n) repi(i, 0, n)
#define per(i, n) peri(i, 0, n)
#define iter(c) __typeof__((c).begin())
#define foreach(i, c) for (iter(c) i = (c).begin(); i != (c).end(); ++i)
#define all(c) (c).begin(), (c).end()
#define mp make_pair

typedef unsigned int uint;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef vector<string> vs;
typedef pair<int, int> pii;

int solve(vi &ms, vi &used, int remain, int index, const vi &prev, vi &cur) {
  int n = ms.size();

  if (remain == 0) {
    vi next;
    return 1 + solve(ms, used, 10, 0, cur, next);
  } else {
    int res = 0;
    repi(i, index, n) {
      if (used[i] || ms[i] > remain)
        continue;
      if (i > 0 && ms[i - 1] == ms[i] &&
          !used[i - 1]) // 1つ前の同じ重さの饅頭を選んでいない
        continue;
      cur.push_back(ms[i]);
      if (prev >= cur) {
        used[i] = 1;
        res = max(res, solve(ms, used, remain - ms[i], i + 1, prev, cur));
        used[i] = 0;
      }
      cur.pop_back();
    }
    return res;
  }
}

int main() {
  for (int n; scanf("%d", &n), n;) {
    vi hist(10);
    rep(i, n) {
      int m;
      scanf("%d", &m);
      hist[m]++;
    }

    int res = 0;
    repi(i, 1, 5) while (hist[i] && hist[10 - i]) {
      res++;
      hist[i]--;
      hist[10 - i]--;
    }
    while (hist[5] >= 2) {
      res++;
      hist[5] -= 2;
    }

    vi ms;
    per(i, 10) ms.insert(ms.end(), hist[i], i);
    vi used(ms.size()), cur;
    res += solve(ms, used, 10, 0, vi(1, 10), cur);

    printf("%d\\n", res);
  }

  return 0;
}