memo[どこまで見た][最後に使った数] = 最後まで作りきれるかどうか
バックトラックしていたら終わらないので、到達可能かどうかをメモ化する。
到達可能と判断できた瞬間にそれまでのパスをなぞる。
const int undef = -100; vector<int> result; const int K = 50 + 1; const int M = 1000 + 1; bool prime[M]; const int fail = 0; const int succ = 1; int memo[K][M]; int buff[K]; string C; bool rec(int nth, int last, const int N) { if (nth == C.size()) return succ; int& ret = memo[nth][last]; if (ret != -1) return ret; ret = fail; for (int next = last + 1; next <= N; ++next) { if ((C[nth] == 'R' && prime[next]) || (C[nth] == 'B' && !prime[next])) { buff[nth] = next; if (rec(nth + 1, next, N) == succ) { ret = succ; for (int i = 0; i <= nth; ++i) { if (result[i] == undef) result[i] = buff[i]; else if (result[i] != buff[i]) result[i] = -1; } } } } return ret; } class ColorfulCards { public: vector <int> theCards(int N, string c) { C = c; fill(prime, prime + M, true); prime[0] = prime[1] = false; for (int i = 2; i * i < M; ++i) { for (int j = 2; i * j < M; ++j) { prime[i * j] = false; } } result.resize(c.size()); fill(result.begin(), result.end(), undef); fill(&memo[0][0], &memo[K - 1][M - 1] + 1, -1); rec(0, 0, N); return result; } };