模拟赛的时候看这道题没有什么头绪,当时有点晕,感冒还没有好,回来以后瞟了一眼题解就明白了,自己实现了一下,也没有很复杂。大概的思路就像拓扑排序一样,需要理解因为涂的是有顺序的,所以我们总可以找打最后涂的那些,即一行或者一列只有一种颜色,把他们记录下来,然后删除这些颜色,再继续找一行一列中只有一个颜色的,最后就是答案。
还要记得用记录数组记录每一行每一列有多少种颜色,否则直接找的话会超时。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<climits>
#include<queue>
#include<vector>
#include<set>
#include<map>
using namespace std;typedef long long ll;
const int INF=0x3f3f3f3f;
const int MAXN=3e3+5;
int n;
char s[MAXN][MAXN];
bool visr[MAXN],visc[MAXN];
int R[MAXN][30]; int C[MAXN][30];struct node
{char cmd;char color;int num;node(char _cmd=0,int _num=0,int _color=0):cmd(_cmd),num(_num),color(_color){}
}q[MAXN<<1];
int tot;bool ok()
{for(int i=0;i<n;i++){if(!visr[i] || !visc[i])return false;}return true;
}void solve()
{tot=2*n;memset(visc,0,sizeof(visc));memset(visr,0,sizeof(visr));char color;bool flag;while(tot>0){for(int i=0;i<n;i++){if(visr[i]) continue;color=' ';flag=true;for(int k=0;k<26;k++){if(R[i][k]){if(' '==color)color=k+'a';else{flag=false;break;}}}if(flag){if(color==' ') color='a';visr[i]=true;q[tot--]=node('h',i+1,color);for(int j=0;j<n;j++){if(s[i][j]!='?'){C[j][s[i][j]-'a']--;}}}}for(int j=0;j<n;j++){if(visc[j]) continue;color=' ';flag=true;for(int k=0;k<26;k++){if(C[j][k]){if(' '==color)color=k+'a';else{flag=false;break;}}}if(flag){if(color==' ') color='a';visc[j]=true;q[tot--]=node('v',j+1,color);for(int i=0;i<n;i++){if('?'!=s[i][j]){R[i][s[i][j]-'a']--;}}}}}for(int i=1,j=2*n;i<=j;i++){printf("%c %d %c\n",q[i].cmd,q[i].num,q[i].color);}
}int main()
{//memset(R,0,sizeof(R));//memset(C,0,sizeof(C));scanf("%d",&n);for(int i=0;i<n;i++){scanf("%s",s[i]);for(int j=0;j<n;j++){if(s[i][j]!='?'){R[i][s[i][j]-'a']++;}}}for(int j=0;j<n;j++){for(int i=0;i<n;i++){if(s[i][j]!='?'){C[j][s[i][j]-'a']++;}}}solve();return 0;
}