G - 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, andC.
- 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, andC.
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: