Official

D - ABC Puzzle Editorial by en_translator


In fact, even when \(N=5\), there are only \(66240\) grids such that each row and column contains exactly one A, B, and C.
Thus, the problem can be solved with a variety of exhaustive search with pruning. We introduce one example here.

Suppose that \(N=5\).
First, focus only on the constraints on rows. We must fulfill the following two conditions:

  • Each row is a permutation of ABC...
  • The leftmost non-. character in the \(i\)-th row from the top is \(R_i\).

For each row, there are only \(20\) conforming permutations. ( \((5 \times 4 \times 3 )/ 3 = 20\) )
Consider trying them for the five rows. (\(20^5\) combinations in total)
We determine the topmost row to the bottommost. Here, none of the following must be violated:

  • Each row contains at most one A, B, and C.
  • The topmost non-. character in the \(j\)-th column from the left is \(R_j\).

Once they are violated, one can stop searching.
After the \(N\) rows are filled, we finally check the following:

  • Each column contains exactly one A, B, and C.

If this is satisfied, then the grid satisfies all the required conditions.

The number of operations in this algorithm is estimated as \(20^5 \times 5^2 = 8 \times 10^7 \times \) (a small constant), but in reality it runs very fast.

Sample code (C++):

#include<bits/stdc++.h>

using namespace std;

vector<vector<string>> row(3);
bool fnd=false;
int n;
string r,c;
vector<string> grid;

void dfs(int i,int fl){
  if(fnd){return;}
  if(i==n){
    if(fl==0){
      cout << "Yes\n";
      for(auto &nx : grid){cout << nx << "\n";}
      fnd=true;
    }
    return;
  }
  for(auto &nx : row[r[i]-'A']){
    grid.push_back(nx);

    int ufl=fl;
    bool und=true;
    for(int j=0;j<n;j++){
      if(nx[j]=='.'){continue;}
      int kind=(nx[j]-'A');
      if((fl&(1<<(4*j+kind)))==0){und=false;break;}
      ufl^=(1<<(4*j+kind));
      if((fl&(1<<(4*j+3)))!=0){
        if(nx[j]!=c[j]){und=false;break;}
        ufl^=(1<<(4*j+3));
      }
    }

    if(und){dfs(i+1,ufl);}
    grid.pop_back();
  }
}

int main(){
  cin >> n >> r >> c;
  string abc="ABC";
  while(abc.size()<n){abc.push_back('.');}
  sort(abc.begin(),abc.end());
  do{
    char tg='.';
    for(auto &nx : abc){
      if(nx!='.'){tg=nx;break;}
    }
    row[tg-'A'].push_back(abc);
  }while(next_permutation(abc.begin(),abc.end()));

  dfs(0,(1<<(4*n))-1);
  if(!fnd){cout << "No\n";}
  return 0;
}

posted:
last update: