読者です 読者をやめる 読者になる 読者になる

GCJ 2016 Round 1B B: Close Match

GoogleCodeJam 競技プログラミング

解法

幅優先

コード

#include <bits/stdc++.h>
using namespace std;

string solve(const string &S, const string &T) {
  int N = S.size();
  queue<tuple<int, int64_t, int64_t>> que;
  que.emplace(0, 0, 0);
  vector<tuple<int64_t, int64_t, int64_t>> ans;
  while (!que.empty()) {
    int64_t i, s, t;
    tie(i, s, t) = que.front();
    que.pop();
    if (i == N) {
      ans.emplace_back(abs(s - t), s, t);
      continue;
    }

    if (s > t) {
      s = S[i] == '?' ? (s * 10 + 0) : (s * 10 + (S[i] - '0'));
      t = T[i] == '?' ? (t * 10 + 9) : (t * 10 + (T[i] - '0'));
      que.emplace(i + 1, s, t);
    } else if (s < t) {
      s = S[i] == '?' ? (s * 10 + 9) : (s * 10 + (S[i] - '0'));
      t = T[i] == '?' ? (t * 10 + 0) : (t * 10 + (T[i] - '0'));
      que.emplace(i + 1, s, t);
    } else {
      if (S[i] == '?' && T[i] == '?') {
        for (int64_t ss = 0; ss < 2; ++ss) {
          for (int64_t tt = 0; tt < 2; ++tt) {
            que.emplace(i + 1, s * 10 + ss, t * 10 + tt);
          }
        }
      } else if (S[i] == '?') {
        t = t * 10 + (T[i] - '0');
        que.emplace(i + 1, s * 10 + (T[i] - '0'), t);
        if (T[i] != '9') que.emplace(i + 1, s * 10 + (T[i] - '0') + 1, t);
        if (T[i] != '0') que.emplace(i + 1, s * 10 + (T[i] - '0') - 1, t);
      } else if (T[i] == '?') {
        s = s * 10 + (S[i] - '0');
        que.emplace(i + 1, s, t * 10 + (S[i] - '0'));
        if (S[i] != '9') que.emplace(i + 1, s, t * 10 + (S[i] - '0') + 1);
        if (S[i] != '0') que.emplace(i + 1, s, t * 10 + (S[i] - '0') - 1);
      } else {
        s = s * 10 + (S[i] - '0');
        t = t * 10 + (T[i] - '0');
        que.emplace(i + 1, s, t);
      }
    }
  }
  sort(ans.begin(), ans.end());
  int64_t i,s, t;
  tie(i, s, t) = ans[0];
  string rS = to_string(s);
  while (rS.size() < S.size()) rS = "0" + rS;
  string rT = to_string(t);
  while (rT.size() < S.size()) rT = "0" + rT;

  return rS + " " + rT;
}

bool check(const string &S, const int i) {
  string tmpi = to_string(i);
  if (tmpi.size() > S.size()) return false;
  while (tmpi.size() < S.size()) tmpi = "0" + tmpi;
  for (int si = 0; si < S.size(); ++si) {
    if (S[si] != tmpi[si] && S[si] != '?') return false;
  }
  return true;
}

string naive_solve(const string &S, const string &T) {
  vector<tuple<int, int, int>> ans;
  for (int i = 0; i < 1000; ++i) {
    if (!check(S, i)) continue;
    for (int j = 0; j < 1000; ++j) {
      if (!check(T, j)) continue;
      ans.emplace_back(abs(i - j), i, j);
    }
  }
  sort(ans.begin(), ans.end());
  int x, s, t;
  tie(x, s, t) = ans[0];
  string rS = to_string(s);
  while (rS.size() < S.size()) rS = "0" + rS;
  string rT = to_string(t);
  while (rT.size() < S.size()) rT = "0" + rT;

  return rS + " " + rT;
}

int main() {
  cin.tie(0);
  ios::sync_with_stdio(false);

  int T;
  cin >> T;
  for (int testcase = 1; testcase <= T; ++testcase) {
    string S, T;
    cin >> S >> T;

    cout << "Case #" << testcase << ": ";
    if (S.size() <= 3) {
      if (naive_solve(S, T) != solve(S, T)) {
        cerr << S << " " << T << endl;
        cerr << naive_solve(S, T) << endl;
        cerr << solve(S, T) << endl;
        assert(false);
      }
    }

    cout << solve(S, T) << endl;
  }
}