您的位置:首页 > 大数据 > 人工智能

ZOJ 3780 Paint the Grid Again (模拟)

2014-04-15 17:27 399 查看
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 ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: