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

#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

typedef istringstream ISS;
typedef ostringstream OSS;
typedef vector<string> VS;
typedef int INT;
typedef vector<INT> VI;
typedef vector<VI> VVI;
typedef pair<INT, INT> II;
typedef vector<II> VII;

template <class T> ostream &operator<<(ostream &os, vector<T> v) {
  for (typename vector<T>::iterator it_i = v.begin(); it_i != v.end(); ++it_i) {
    os << *it_i << ", ";
  }
  return os;
}

const string YES = "OK";
const string NO = "NA";
const int SIZE = 13;
const int BIT_SIZE = 1 << SIZE;

double d[SIZE][SIZE];
double memo[SIZE][SIZE][BIT_SIZE];
VI R;
int n;

inline double sq(double x) { return x * x; }

inline double getLength(double a, double b) {
  return sqrt(sq(a + b) - sq(a - b));
}

inline bool isValidSub(int a, int left, int right, int s) {
  int ba = 1 << a;
  if (left == a || right == a)
    return false;
  if ((s & ba) == 0)
    return false;
  return true;
}

inline bool isValid(int a, int b, int left, int right, int s) {
  int ba = 1 << a;
  int bb = 1 << b;
  if (left == a || right == a)
    return false;
  if (left == b || right == b)
    return false;
  if ((s & ba) == 0)
    return false;
  if ((s & bb) == 0)
    return false;
  return true;
}

double rec(int left, int right, int state) {
  double &res = memo[left][right][state];
  if (res > 0)
    return res;
  double cnt = __builtin_popcount(state);
  if (cnt == 1) {
    return res = 2 * R[left];
  }
  if (cnt == 2) {
    if (R[left] == R[right])
      return res = 4 * R[left];
    return res = R[left] + R[right] + d[left][right];
  }
  res = INT_MAX;
  for (int i = 0; i < n; ++i) {
    if (!isValidSub(i, left, right, state))
      continue;
    for (int j = 0; j < n; ++j) {
      if (!isValidSub(j, left, right, state))
        continue;
      if (cnt > 3 && i == j)
        continue;
      double x = R[left] + R[right] - R[i] - R[j] +
                 rec(i, j, (state ^ (1 << left)) ^ (1 << right)) + d[left][i] +
                 d[right][j];
      res = min(res, x);
    }
  }
  return res;
}

string solve(int w) {
  fill((double *)memo, (double *)memo + SIZE * SIZE * BIT_SIZE, -1.0);
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (R[i] == R[j])
        d[i][j] = 2 * R[i];
      else
        d[i][j] = getLength(R[i], R[j]);
    }
  }

  double res = INT_MAX;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (n > 1 && i == j)
        continue;
      res = min(res, rec(i, j, (1 << n) - 1));
    }
  }
  return (int)ceil(res) <= w ? YES : NO;
}

int main() {
  string line;
  while (getline(cin, line)) {
    ISS iss(line);
    int w;
    iss >> w;
    R.clear();
    int r;
    while (iss >> r)
      R.push_back(r);
    n = R.size();
    cout << solve(w) << endl;
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <iostream>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <vector>
using namespace std;

typedef istringstream ISS;
typedef ostringstream OSS;
typedef vector<string> VS;
typedef int INT;
typedef vector<INT> VI;
typedef vector<VI> VVI;
typedef pair<INT, INT> II;
typedef vector<II> VII;

template <class T> ostream &operator<<(ostream &os, vector<T> v) {
  for (typename vector<T>::iterator it_i = v.begin(); it_i != v.end(); ++it_i) {
    os << *it_i << ", ";
  }
  return os;
}

const string YES = "OK";
const string NO = "NA";

double sq(double x) { return x * x; }

double getLength(double a, double b) {
  return fabs(sqrt(sq(a + b)) - sq(a - b));
}

const int SIZE = 13;
const int BIT_SIZE = 1 << SIZE;
const int NONE = -1.0;
double d[SIZE][SIZE];
double memo[SIZE][SIZE][BIT_SIZE];
VI R;
int n;

bool isValid(int a, int b, int left, int right, int s) {
  int ba = 1 << a;
  int bb = 1 << b;
  if (left == a || right == a)
    return false;
  if (left == b || right == b)
    return false;
  if ((s & ba) == 0)
    return false;
  if ((s & bb) == 0)
    return false;
  return true;
}

double rec(int left, int right, int state) {
  double &res = memo[left][right][state];
  if (res > NONE)
    return res;
  double cnt = __builtin_popcount(state);
  if (cnt == 1) {
    return res = 2 * R[left];
  }
  if (cnt == 2) {
    if (R[left] == R[right])
      return res = 4 * R[left];
    return res = R[left] + R[right] + d[left][right];
  }
  res = INT_MAX;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (!isValid(i, j, left, right, state))
        continue;
      if (cnt > 3 && i == j)
        continue;
      double x = R[left] + R[right] - R[i] - R[j] +
                 rec(i, j, state ^ (1 << left) ^ (1 << right)) + d[left][i] +
                 d[right][i];
      res = min(res, x);
    }
  }
  return res;
}

string solve(int w) {
  fill((double *)memo, (double *)memo + SIZE * SIZE * BIT_SIZE, NONE);
  double res = INT_MAX;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (n > 1 && i == j)
        continue;
      res = min(res, rec(i, j, (1 << n) - 1));
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      if (R[i] == R[j])
        d[i][j] = 2 * R[i];
      else
        d[i][j] = getLength(R[i], R[j]);
    }
  }
  return res <= w ? YES : NO;
}

int main() {
  string line;
  while (getline(cin, line)) {
    ISS iss(line);
    int w;
    iss >> w;
    R.clear();
    int r;
    while (iss >> r)
      R.push_back(r);
    n = R.size();
    cout << solve(w) << endl;
  }
  return 0;
}