思路:
如果这张图能涂成的话,那么我们每次一定能找到一行或一列一样的,涂完的这行或者列就可以是任意的了,在接着向前边的状态变换。注意题目要求的字典序最小,那么可以列得在行前,所以我们从后往前处理时先处理行。然后同行或同列,从大到小处理。
#include <iostream>
#include <cstdio>
#include <string.h>
#include <queue>
#include <cmath>
#include <algorithm>
#include <map>
typedef long long int lli;
using namespace std;
int ma[550][550];
char s[550];
int ans[1010];
int ans2[1010];// 0 stand of column 1 stand of row
int r[505];
int c[505];
int main(){
int t;
cin>>t;
int n;
while(t--){
scanf("%d",&n);
memset(ma,0,sizeof(ma));
memset(r,0,sizeof(r));
memset(c,0,sizeof(c));
for(int i = 1;i <= n;i++){
scanf("%s",s);
for(int j = 0;j < n;j++){
if(s[j] == 'X'){
ma[i][j+1] = 1;
}
else{
ma[i][j+1] = -1;
}
}
}
int flag = 0;
int cnt = 0;
int lastflag = 0;
while(flag != n*n){
int flag2 = 1;
for(int i = n;flag != n*n && i >= 1;i--){
if(r[i] == 1) continue;
int temp = 1;
flag2 = 1;
int cntof0 = 0;
for(int j = 1;j <= n;j++){
if(ma[i][j] == 0){
cntof0++;
continue;
}
if(ma[i][j] != temp){
flag2 = 0;
break;
}
}
if(cntof0 == n){
r[i] = 1;
continue;
}
if(flag2 == 1){
ans[cnt] = i;
ans2[cnt++] = 1;
for(int j = 1;j <= n;j++){
ma[i][j] = 0;
}
r[i] = 1;
flag += (n - cntof0);
}
}
flag2 = 1;
for(int j = n;flag != n*n && j >= 1;j--){
if(c[j] == 1) continue;
int temp = -1;
flag2 = 1;
int cntof0 = 0;
for(int i = 1;i <= n;i++){
if(ma[i][j] == 0){
cntof0++;
continue;
}
if( ma[i][j] != temp){
flag2 = 0;
break;
}
}
if(cntof0 == n){
c[j] = 1;
continue;
}
if(flag2 == 1){
ans[cnt] = j;
ans2[cnt++] = 0;
for(int i = 1;i <= n;i++){
ma[i][j] = 0;
}
c[j] = 1;
flag += (n - cntof0);
}
}
if(lastflag == flag ) break;
lastflag = flag;
}
if(lastflag == flag && flag != n*n){
printf("No solution\n");
continue;
}
for(int i = cnt-1;i >= 0;i--){
if(i != cnt-1) printf(" ");
if(ans2[i] == 0){
printf("C%d",ans[i]);
}
else{
printf("R%d",ans[i]);
}
}
puts("");
}
}