[ABC326] D - ABC Puzzle

[Q] https://atcoder.jp/contests/abc326/tasks/abc326_d

考察
1. 実装重そう。とりあえず全探索を考える。
2. 25マスに4通り"ABC."が入るので4^25通りの探索。これはTLE。
3. 枝刈り条件がたくさんあるので、削っていけばdfsで間に合う気がする
・自分のマスにAをおくとき、行と列にすでにAがあればおかない
・行を置ききったあと、行がABCを網羅していなければダメ
・列を置ききったあと、列がABCを網羅していなければダメ
4. 終了条件は、25マス埋めた後に左文字列と上文字列が指示と同じか評価。

実装

int main() {
  cincout();
  
  ll N;
  string R, C;
  cin >> N >> R >> C;

  vector<ll> h(N), w(N); // h[0]=111: 0列目はABCすべて使用済み
  vector<string> S(N, string(N, '.')); // 答え。backtrackで埋めていく

  // マスpにABCをおけるか
  auto canPut=[&](ll p, ll a)->bool{
    if (is_pop(h[p % N], a)) return false;
    if (is_pop(w[p / N], a)) return false;
    return true;
  };

  // 25マス見終わったあとの盤面評価
  auto bingo=[&]()->bool{
    // ABCが行と列でそろっているか
    rep(i, N) if (__bt(h[i]) != 3) return false;
    rep(i, N) if (__bt(w[i]) != 3) return false;
    string r, c;
    // 最も左のABCを取得
    rep(i, N) rep(j, N){
      if (S[i][j] == '.') continue;
      r += S[i][j];
      break;
    }
    // 最も上のABCを取得
    rep(i, N) rep(j, N){
      if (S[j][i] == '.') continue;
      c += S[j][i];
      break;
    }
    if (r == R && c == C) return true;
    return false;
  };

  // backtrackで、25マス探索
  std::function<bool(ll)> dfs = [&](ll p)->bool{
    // TLEのため枝刈り
    // 0行目を埋め終わった時点で、ABCがそろっていないとダメ
    if (p % N == 0 && p > 0){
      if (__bt(w[(p - 1) / N]) != 3) return false;
    }
    // 0列目を埋め終わった時点で、ABCがそろっていないとダメ
    if ((p - 1) / N == N - 1){
      if (__bt(h[(p - 1) % N]) != 3) return false;
    }
    // 解答を満たすか判定
    if (p == N * N){
      if (bingo()){
        cout << "Yes" << endl;
        rep(i, N) cout << S[i] << endl;
        return true;
      }
      return false;
    }
    rep(i, 3){ // "ABC"[i]
      if (!canPut(p, i)) continue;
      // 設置
      h[p % N] += (1 << i);
      w[p / N] += (1 << i);
      S[p / N][p % N] = "ABC"[i];
      if (dfs(p + 1)) return true;
      // 復元 backtrack
      h[p % N] -= (1 << i);
      w[p / N] -= (1 << i);
    }
    S[p / N][p % N] = '.';
    if (dfs(p + 1)) return true;
    return false;
  };
  if (dfs(0)) return 0;
  cout << "No" << endl;
}

https://atcoder.jp/contests/abc326/submissions/47021832


この記事が気に入ったらサポートをしてみませんか?