模擬賽的時候看這道題沒有什么頭緒,當時有點暈,感冒還沒有好,回來以后瞟了一眼題解就明白了,自己實現了一下,也沒有很復雜。大概的思路就像拓撲排序一樣,需要理解因為涂的是有順序的,所以我們總可以找打最后涂的那些,即一行或者一列只有一種顏色,把他們記錄下來,然后刪除這些顏色,再繼續找一行一列中只有一個顏色的,最后就是答案。
還要記得用記錄數組記錄每一行每一列有多少種顏色,否則直接找的話會超時。
#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;
}