可以拓扑排序,也可以贪心模拟。
由于行与列必有1交点,如果有某行可删除,则任一列肯定无法删除。
每次先判断是否全是‘-’,如果是则完成,输出答案。
每次找到字典序最大的要删除的某行或某列,删除。
如果没找到,则表示No solution.
#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int N=1502;
int tt,n;
char mp[N][N];
bool col[N],row[N];
bool check(){//是否全部完成
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(mp[i][j]!='-') return 0;
return 1;
}
char ch[2*N];
int id[2*N];
//字典序 C<R 1<2
int find(int cnt){
//行X
for(int i=n;i>=1;i--){
if(row[i]) continue;
int j,t=0;
for(j=1;j<=n;j++){
if(mp[i][j]=='O') break;
else if(mp[i][j]=='-') t++;
}
if(t==n){
row[i]=1;
continue;
}
if(j==(n+1)){//行i可清0
row[i]=1;
ch[cnt]='R';
id[cnt]=i;
for(int k=1;k<=n;k++)
mp[i][k]='-';
return 1;
}
}
//列O
for(int i=n;i>=1;i--){
if(col[i]) continue;
int j,t=0;
for(j=1;j<=n;j++){
if(mp[j][i]=='X') break;
else if(mp[j][i]=='-') t++;
}
if(t==n){
col[i]=1;
continue;
}
if(j==(n+1)){//列i可清0
col[i]=1;
ch[cnt]='C';
id[cnt]=i;
for(int k=1;k<=n;k++)
mp[k][i]='-';
return 1;
}
}
return 0;
}
int main(){
cin>>tt;
while(tt--){
cin>>n;
for(int i=1;i<=n;i++)
scanf("%s",mp[i]+1);
memset(col,0,sizeof col);
memset(row,0,sizeof row);
int cnt=0,goal=1;
while(1){
if(check()) break;
int t=find(cnt++);
if(t==0){ goal=0;break;}
}
if(!goal){
printf("No solution\n");
continue;
}
for(int i=cnt-1;i>=0;i--){
printf("%c%d",ch[i],id[i]);
printf("%c",i?' ':'\n');
}
}
return 0;
}