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

#include <cstdio>
#include <vector>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

bool is_valid(const char *a, const char *b, int hit, int blow) {
  rep(i, 4) rep(j, 4) if (a[i] == b[j]) {
    if (i == j)
      hit--;
    else
      blow--;
  }
  return hit == 0 && blow == 0;
}

int main() {
  vector<int> cand0; // どの桁の数字も異なるような 4 桁の数
  rep(i, 10000) {
    char s[5];
    sprintf(s, "%04d", i);
    if (!(s[0] == s[1] || s[0] == s[2] || s[0] == s[3] || s[1] == s[2] ||
          s[1] == s[3] || s[2] == s[3]))
      cand0.push_back(i);
  }

  for (int n; scanf("%d", &n), n;) {
    vector<int> in(n), hit(n), blow(n);
    rep(i, n) scanf("%d%d%d", &in[i], &hit[i], &blow[i]);

    // 入力された質問に矛盾しない数全体
    vector<int> cand;
    rep(j, cand0.size()) {
      char s[5];
      sprintf(s, "%04d", cand0[j]);
      bool ok = true;
      rep(i, n) {
        char t[5];
        sprintf(t, "%04d", in[i]);
        if (!is_valid(s, t, hit[i], blow[i])) {
          ok = false;
          break;
        }
      }
      if (ok)
        cand.push_back(cand0[j]);
    }

    if (cand.size() == 1) {
      printf("%04d\\n", cand[0]);
      continue;
    }

    if (cand.size() > 16) {
      puts("????");
      continue;
    }

    int ans = -1;
    rep(i, cand0.size()) {
      char s[5];
      sprintf(s, "%04d", cand0[i]); // 最後の 1 回に発言するべき数

      bool ok = true;
      vector<int> reply(cand.size());
      rep(j, cand.size()) {
        char t[5];
        sprintf(t, "%04d", cand[j]);
        int hit = 0, blow = 0;
        rep(k, 4) rep(l, 4) if (s[k] == t[l]) {
          if (k == l)
            hit++;
          else
            blow++;
        }
        reply[j] = hit * 10 + blow;
        rep(k, j) if (reply[k] == reply[j]) {
          ok = false;
          break;
        }
      }

      if (ok) { // 真の解がどれであったとしても特定できるとき
        if (ans == -1) {
          ans = cand0[i];
          break;
        }
      }
    }

    if (ans != -1)
      printf("%04d\\n", ans);
    else
      puts("????");
  }

  return 0;
}

Error: TLE

Fixed submission:

#include <cstdio>
#include <vector>

#define rep(i, n) for (int i = 0; i < (n); i++)

using namespace std;

bool is_valid(const char *a, const char *b, int hit, int blow) {
  rep(i, 4) rep(j, 4) if (a[i] == b[j]) {
    if (i == j)
      hit--;
    else
      blow--;
  }
  return hit == 0 && blow == 0;
}

int main() {
  vector<int> cand0; // どの桁の数字も異なるような 4 桁の数
  rep(i, 10000) {
    char s[5];
    sprintf(s, "%04d", i);
    if (!(s[0] == s[1] || s[0] == s[2] || s[0] == s[3] || s[1] == s[2] ||
          s[1] == s[3] || s[2] == s[3]))
      cand0.push_back(i);
  }

  for (int n; scanf("%d", &n), n;) {
    vector<int> in(n), hit(n), blow(n);
    rep(i, n) scanf("%d%d%d", &in[i], &hit[i], &blow[i]);

    // 入力された質問に矛盾しない数全体
    vector<int> cand;
    rep(j, cand0.size()) {
      char s[5];
      sprintf(s, "%04d", cand0[j]);
      bool ok = true;
      rep(i, n) {
        char t[5];
        sprintf(t, "%04d", in[i]);
        if (!is_valid(s, t, hit[i], blow[i])) {
          ok = false;
          break;
        }
      }
      if (ok)
        cand.push_back(cand0[j]);
    }

    if (cand.size() == 1) {
      printf("%04d\\n", cand[0]);
      continue;
    }

    int ans = -1;
    rep(i, cand0.size()) {
      char s[5];
      sprintf(s, "%04d", cand0[i]); // 最後の 1 回に発言するべき数

      bool ok = true;
      vector<int> reply(cand.size());
      rep(j, cand.size()) {
        char t[5];
        sprintf(t, "%04d", cand[j]);
        int hit = 0, blow = 0;
        rep(k, 4) rep(l, 4) if (s[k] == t[l]) {
          if (k == l)
            hit++;
          else
            blow++;
        }
        reply[j] = hit * 10 + blow;
        rep(k, j) if (reply[k] == reply[j]) {
          ok = false;
          break;
        }
      }

      if (ok) { // 真の解がどれであったとしても特定できるとき
        if (ans == -1) {
          ans = cand0[i];
          break;
        }
      }
    }

    if (ans != -1)
      printf("%04d\\n", ans);
    else
      puts("????");
  }

  return 0;
}