给一个白板 每一次可以把一行涂黑或者把一列涂白 逆向考虑的话 每涂完一次都会有一行全黑或者有一列全白 找出来更新当前状态 然后挑字典序最大的继续更新即可
若最后能把每个空都更新一遍就是一张符合题意的图
至于次数最少的问题 其实只要是一张存在正确着色方式的图 那么该涂多少次都是固定不变的 因为每一次只能把一行涂黑或者把一列涂白 而不是每一行每一列涂成黑白都行(一开始就是看错题了的 还思考了很久..)
#include <bits/stdc++.h> 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; }