Paint the Grid Again
题目链接: ZOJ - 3780题意:一个N*N的格子, 一开始是空白的, 每次可以将一列变为O或将一行变为X;给出最终的状态, 问最少需要多少个操作才能将白纸变为给出的状态, 若可以按字典序输出, 操作, 反之输出“No solution”;
在有O的一列中有X, 那么一定是在这一列先刷了O, 再在对应行刷X;
在有X的一行中有O, 那么一定是在这一行先刷了X, 再在对应列刷O;
现在将行的点与列的点看作不同的点, 可以看作是一种拓扑关系;
#include <iostream> #include <cstring> #include <algorithm> #include <cstdio> #include <vector> #include <queue> using namespace std; int n; char maze[510][510]; int cnt[1100], fr[510], fc[510]; vector<int> vec[1100]; void init(){ memset(fc, 0, sizeof(fc)); memset(fr, 0, sizeof(fr)); memset(cnt, 0, sizeof(cnt)); for(int i=0; i<n+510; i++) vec[i].clear(); for(int i=0; i<n; i++){ for(int j=0; j<n; j++){ if(maze[i][j]=='O') fc[j]=1; else fr[i]=1; } } for(int i=0; i<n; i++){ if(!fr[i]) continue; for(int j=0; j<n; j++){ if(maze[i][j]=='O'){ vec[i].push_back(j+510); cnt[j+510]++; } } } for(int j=0; j<n; j++){ if(!fc[j]) continue; for(int i=0; i<n; i++){ if(maze[i][j]=='X'){ vec[j+510].push_back(i); cnt[i]++; } } } return; } void topsort(){ priority_queue<int, vector<int>, greater<int> > q; for(int i=0; i<n+510; i++){ if(cnt[i]==0&&vec[i].size()!=0){ q.push(i); } } int flag=0; while(!q.empty()){ int tmp=q.top(); q.pop(); for(int i=0; i<vec[tmp].size(); i++){ int t=vec[tmp][i]; cnt[t]--; if(!cnt[t]){ q.push(t); } } if(tmp<510) printf("%sR%d", flag?" ":"", tmp+1), flag=1; else printf("%sC%d", flag?" ":"", tmp-510+1), flag=1; } if(flag) printf("\n"); else printf("No solution\n"); return; } int main(){ int T; cin >> T; while(T--){ scanf("%d", &n); for(int i=0; i<n; i++) scanf("%s", maze[i]); init(); topsort(); } return 0; }