ZOJ 3780 Paint the Grid Again (模拟)

来源:互联网 发布:中企动力源码下载 编辑:程序博客网 时间:2024/06/06 02:32

OJ题目:click here~~

题意分析:n*m的格子,开始每个格子中不是X,也不是O。给出目标状态。有且只有两种操作,1,一整行刷,该行变成X;2,一整列刷,该列变成O。字典序输出得到目标状态,最少的操作序列。列的字典序小于行,同样的列操作中,列号小的字典序小,行同理。

模拟操作过程。从后向前。如果行全为X 或者 列全为O,一定在后面操作。在操作行时,如果某列中唯独在该行处是X,则该列一定在该行之前操作。在操作列时,如果某行中唯独在该列处是O,则该行一定在操作该列之前操作。依次往前推,如果队列已空,依然有行或者列没有操作,则为无解情况。

AC_CODE

typedef long long LL;const int  Max_N = 508 ;char  g[Max_N][Max_N] ;int   n , row[Max_N] , col[Max_N] ;vector <int> stak ;vector <int> ::iterator it  ;bool  yes[Max_N<<1] ;bool  cmp(int a , int b){return a > b ;}void  Ans(){      int i , j , u ;      vector<int> ans ;      sort(stak.begin() , stak.end() , cmp) ;//序号从大到小排序(其实,栈里面要么全是行,要么全是列)      queue<int> que ;      for(it = stak.begin() ; it != stak.end() ; it++){            que.push(*it) ;            yes[*it] = 1 ;      }      stak.clear() ;      while(! que.empty()){            ans.push_back(u = que.front())  ;//整行都是X , 或者整列都是O,该行或者该列一定最后刷            que.pop() ;            if(u > n){//如果是行                 u -= n ;//取出行号                 for(i = 1 ; i <= n ; i++){                       col[i]++ ;                       if(!yes[i] && col[i] == n)//如果满足,说明刷该行之前先刷列                          stak.push_back(i) ;                 }            }            else{//如果是列                 for(i = 1 ; i <= n ; i++){                       row[i]++ ;                       if(!yes[i+n] && row[i] == n)//如果满足,说明刷该列之前先刷行                        stak.push_back(i+n) ;                 }            }            sort(stak.begin() , stak.end() , cmp) ;//从大到小排列            for(it = stak.begin() ; it != stak.end() ; it++){                 que.push(*it) ;//需要刷的逆序入队,因为是从后向前考虑                 yes[*it] = 1 ;//标记已刷            }            stak.clear() ;      }      for(i = 1 ; i <= n+n ; i++){           if(!yes[i]){//如果队列已经空,依然存在没有刷完的,说明无解                  puts("No solution") ;                  return ;           }      }      std::reverse(ans.begin() , ans.end()) ;//以上为反向考虑,现逆序      it = ans.begin() ;      printf("%c" , *it <= n ? 'C' : 'R') ;      printf("%d" , *it <= n ? *it : *it - n) ;      for(it++ ; it != ans.end() ; it++){          printf(" %c" , *it <= n ? 'C' : 'R') ;          printf("%d" , *it <= n ? *it : *it - n) ;      }      puts("")  ;}int  main(){     int t  , i  , j ;     cin>>t ;     while(t--){          cin>>n ;          memset(row , 0 , (n+1)*sizeof(int)) ;          memset(col , 0 , (n+1)*sizeof(int)) ;          memset(yes , 0 , (n+n+1)*sizeof(bool)) ;          for(i = 1 ; i <= n ; i++)  scanf("%s" ,g[i]+1) ;          for(i = 1 ; i <= n ; i++){              for(j = 1 ; j <= n ; j++) if(g[i][j] == 'X') row[i]++ ;//统计i行的X个数              if(row[i] == n) stak.push_back(i+n)  ;//如果该行全是X ,则该行需要刷一次              else if(row[i] == 0) yes[i+n] = 1 ;//如果该行没有X , 则该行不需要刷,即已经搞定          }                                      //行需要刷,把行号加n入栈,因为行的字典序比列大          for(j = 1 ; j <= n ; j++){              for(i = 1 ; i <= n ; i++)  if(g[i][j] == 'O') col[j]++ ;//统计j列的O个数              if(col[j] == n) stak.push_back(j) ;//如果该列全是O , 则该列需要刷一次              else if(col[j] == 0) yes[j] = 1 ;//如果该列没有O,则该列不需要刷,即已经搞定          }          Ans() ;     }     return 0 ;}


0 0