xtu1369

这是个标题

Black White Chess

题目描述

一个4×4的格子棋盘,每个格子上有白棋或者黑棋,我们可以做下面三种操作:

把同一行的棋子翻转(白变成黑,黑变成白)
把同一列的棋子翻转
把一个2×2的格子里的棋子翻转
求最少多少步操作,我们可以得到全部是黑的或者全部是白的棋局。

输入

第一行是一个整数T(1≤T≤100000),表示样例的个数。 以后每行一个样例,每行是一个16位的二进制码,依次表示从第1行到第4行的棋局。

输出

每行输出一个样例的结果,如果无法达到目标,输出“-1”。

样例输入

5
0000000000000000
1111111111111111
0000111100001111
1000000000000000
1100000000000011

样例输出

0
0
2
-1
4

BFS

思路:挺巧妙的,从全0和全1状态开始BFS出每种局面,因为局面最多2^16种,所以不会超时。对于每次查询,直接输出即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#include<bits/stdc++.h>
using namespace std;
#define Debug(x) cout<<#x<<':'<<x<<endl
#define INF 0x7fffffff
typedef long long ll;
typedef pair<ll,ll> P;
const ll maxn=1e5+11;
ll vis[maxn],ans[maxn];
string row(string s,ll x){
for(ll i=4*(x-1);i<4*x;i++) s[i]=(s[i]=='0'?'1':'0');
return s;
}
string col(string s,ll x){
for(ll i=x-1;i<16;i+=4) s[i]=(s[i]=='0'?'1':'0');
return s;
}
string squ(string s,ll x){
ll b=(x-1)/3+x-1;
for(ll i=b;i<=b+1;i++) s[i]=(s[i]=='0'?'1':'0');
for(ll i=b+4;i<=b+4+1;i++) s[i]=(s[i]=='0'?'1':'0');
return s;
}
ll hash_1(string s){
ll sum=0;
for(ll i=0;i<s.length();i++) sum=sum*2+s[i]-'0';
return sum;
}
void bfs(){
queue<pair<string,ll>> q;
string s1,s2;
for(ll i=0;i<16;i++) s1+='0';
for(ll i=0;i<16;i++) s2+='1';
q.push({s1,0});q.push({s2,0});
while(!q.empty()){
string s=q.front().first;
ll dd=q.front().second;
q.pop();
ll x=hash_1(s);
if(vis[x]) continue;
vis[x]=1,ans[x]=dd;
for(ll i=1;i<=4;i++) q.push({row(s,i),dd+1});
for(ll i=1;i<=4;i++) q.push({col(s,i),dd+1});
for(ll i=1;i<=9;i++) q.push({squ(s,i),dd+1});
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
bfs();
ll ca;cin>>ca;
while(ca--){
string s;cin>>s;
ll x=hash_1(s);
if(vis[x]) cout<<ans[x]<<endl;
else cout<<-1<<endl;
}
return 0;
}