点击打开链接
给一个白板 每一次可以把一行涂黑或者把一列涂白 逆向考虑的话 每涂完一次都会有一行全黑或者有一列全白 找出来更新当前状态 然后挑字典序最大的继续更新即可
若最后能把每个空都更新一遍就是一张符合题意的图
至于次数最少的问题 其实只要是一张存在正确着色方式的图 那么该涂多少次都是固定不变的 因为每一次只能把一行涂黑或者把一列涂白 而不是每一行每一列涂成黑白都行(一开始就是看错题了的 还思考了很久..)
using namespace std;
struct node
{
int id;
char ch;
};
node ans[1010];
int b[510],w[510],row[510],col[510];
int n;
char mp[510][510];
void toposort()
{
int i,j,sum,flag,cnt;
memset(row,0,sizeof(row));
memset(col,0,sizeof(col));
sum=n*n,cnt=0;
while(sum>0)
{
flag=0;
for(i=n;i>=1;i--)
{
if(b[i]==n&&!row[i])
{
flag=1;
row[i]=1;
for(j=1;j<=n;j++)
{
if(!col[j]) sum--;
mp[i][j]='*';
w[j]++;
}
cnt++;
ans[cnt].id=i,ans[cnt].ch='R';
break;
}
}
if(!flag)
{
for(j=n;j>=1;j--)
{
if(w[j]==n&&!col[j])
{
flag=1;
col[j]=1;
for(i=1;i<=n;i++)
{
if(!row[i]) sum--;
mp[i][j]='*';
b[i]++;
}
cnt++;
ans[cnt].id=j,ans[cnt].ch='C';
break;
}
}
}
if(!flag) break;
}
if(sum==0)
{
for(i=cnt;i>=1;i--)
{
printf("%c%d",ans[i].ch,ans[i].id);
if(i>1) printf(" ");
else printf("\n");
}
}
else
{
printf("No solution\n");
}
return;
}
int main()
{
int t,i,j;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%s",mp[i]+1);
}
memset(b,0,sizeof(b));
memset(w,0,sizeof(w));
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(mp[i][j]=='X') b[i]++;
else w[j]++;
}
}
toposort();
}
return 0;
}