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
, 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: