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

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

#define whole(xs) (xs).begin(), (xs).end()

namespace {
template <class T> ostream &operator<<(ostream &os, const vector<T> &vs) {
  if (vs.empty())
    return os << "[]";
  os << "[" << vs[0];
  for (int i = 1; i < vs.size(); i++)
    os << " " << vs[i];
  return os << "]";
}

typedef long double real;

real EPS = 1e-9;

real R;
int S;
vector<int> W;
void input() {
  cin >> R >> S;
  W.clear();
  W.resize(S);
  for (int i = 0; i < S; i++) {
    cin >> W[i];
  }
}

real solve();

vector<int> pat;
void init() {
  real ans = -1;
  pat.clear();
  for (int k = 0; k < S - 1; k++)
    pat.push_back(0);
  for (int i = 0; i < S; i++)
    pat.push_back(W[i]);
  ans = max(ans, solve());
  if (ans < 0) {
    cout << -1 << endl;
  } else {
    printf("%.18Lf\\n", ans);
  }
}

struct State {
  int w;
  real left, right;
  State(int w, real left, real right) : w(w), left(left), right(right) {}
};

real parse() {
  vector<State> stack;
  real ans = 0;
  for (int i = 0; i < pat.size(); i++) {
    if (pat[i] == 0) { // 結合
      if (stack.size() < 2)
        return -1.0;
      assert(stack.size() >= 2);
      State a = stack.back();
      stack.pop_back();
      State b = stack.back();
      stack.pop_back();
      int w = a.w + b.w;
      real L = 1.0 / w * b.w, R = 1.0 / w * a.w;
      real nleft = max(L + a.left, b.left - R);
      real nright = max(R + b.right, a.right - L);
      stack.push_back(State(a.w + b.w, nleft, nright));
      ans = max(ans, nleft + nright);
    } else {
      assert(pat[i] >= 1); // 石
      stack.push_back(State(pat[i], 0, 0));
    }
  }
  assert(stack.size() == 1);
  return ans;
}

real solve() {
  real ans = -1.0;
  sort(whole(pat));
  do {
    real c = parse();
    // printf("c: %.18Lf  ", c); cout << pat << endl;
    if (c > R + EPS)
      continue;
    ans = max(c, ans);
  } while (next_permutation(whole(pat)));
  return ans;
}
} // namespace

int main() {
  int T;
  cin >> T;
  for (int i = 0; i < T; i++) {
    input();
    init();
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

#define whole(xs) (xs).begin(), (xs).end()

namespace {
template <class T> ostream &operator<<(ostream &os, const vector<T> &vs) {
  if (vs.empty())
    return os << "[]";
  os << "[" << vs[0];
  for (int i = 1; i < vs.size(); i++)
    os << " " << vs[i];
  return os << "]";
}

typedef long double real;

real R;
int S;
vector<int> W;
void input() {
  cin >> R >> S;
  W.clear();
  W.resize(S);
  for (int i = 0; i < S; i++) {
    cin >> W[i];
  }
}

real solve();

vector<int> pat;
void init() {
  real ans = -1;
  for (int j = 0; j <= S - 1; j++) {
    pat.clear();
    for (int k = 0; k < j; k++)
      pat.push_back(0);
    for (int k = j; k < S - 1; k++)
      pat.push_back(-1);
    for (int i = 1; i <= S; i++)
      pat.push_back(i);
    ans = max(ans, solve());
  }
  if (ans < 0) {
    cout << -1 << endl;
  } else {
    printf("%.18Lf\\n", ans);
  }
}

struct State {
  int w;
  real left, right;
  State(int w, real left, real right) : w(w), left(left), right(right) {}
};

real parse() {
  vector<State> stack;
  real ans = -1.0;
  for (int i = 0; i < pat.size(); i++) {
    if (pat[i] <= 0) { // 結合
      if (stack.size() < 2)
        return -1.0;
      assert(stack.size() >= 2);
      State a = stack.back();
      stack.pop_back();
      State b = stack.back();
      stack.pop_back();
      real nleft, nright;
      int w = (a.w + b.w);
      if (pat[i] == 0) {
        nleft = 1.0 / w * b.w + a.left;
        nright = 1.0 / w * a.w + b.right;
        stack.push_back(State(a.w + b.w, nleft, nright));
      } else {
        assert(pat[i] == -1);
        nleft = 1.0 / w * a.w + b.left;
        nright = 1.0 / w * b.w + a.right;
        stack.push_back(State(a.w + b.w, nleft, nright));
      }
      if (nright + nleft > R)
        return -1;
      ans = max(ans, nright + nleft);
    } else {
      assert(pat[i] >= 1); // 石
      stack.push_back(State(W[pat[i] - 1], 0, 0));
    }
  }
  return ans;
}

bool check() {
  if (pat[0] <= 0 || pat[1] <= 0)
    return false;
  int c = 0;
  for (int i = 0; i < pat.size(); i++) {
    if (pat[i] <= 0) {
      if (c < 2)
        return false;
      c--;
    } else {
      c++;
    }
  }
  return true;
}

real solve() {
  if (S == 1) {
    return 0;
  }
  real ans = -1.0;
  sort(whole(pat));
  do {
    if (!check())
      continue;
    real c = parse();
    if (c > R)
      continue;
    ans = max(c, ans);
  } while (next_permutation(whole(pat)));
  return ans;
}
} // namespace

int main() {
  int T;
  cin >> T;
  for (int i = 0; i < T; i++) {
    input();
    init();
  }
  return 0;
}