「bzoj4171」「HNMTC2015_#3」rhl的游戏 - 高斯消元解异或方程组 | Bill Yang's Blog

「bzoj4171」「HNMTC2015_#3」rhl的游戏 - 高斯消元解异或方程组

题目大意

    RHL最近迷上一个小游戏:Flip it。游戏的规则很简单,在一个$N\times M$的格子上,有一些格子是黑色,有一些是白色。每选择一个格子按一次,格子以及周围边相邻的格子都会翻转颜色(边相邻指至少与该格子有一条公共边的格子),黑变白,白变黑。
    RHL希望把所有格子都变成白色的。不幸的是,有一些格子坏掉了,无法被按下。这时,它可以完成游戏吗?


题目分析

发现我之前写的高斯消元基本上都是错的。

上一道题类似。
把坏掉的格子也放入方程组即可。

上高斯约旦。
最后用自由变元判断是否有解。


代码

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
59
60
61
62
63
64
65
#include<bits/stdc++.h>
using namespace std;
inline int Get_Int() {
int num=0,bj=1;
char x=getchar();
while(!isdigit(x)) {if(x=='-')bj=-1;x=getchar();}
while(isdigit(x)) {num=num*10+x-'0';x=getchar();}
return num*bj;
}
const int maxn=265;
int n,m,k;
char s[maxn];
bitset<maxn> a[maxn<<1],f[maxn][maxn];
bool Gauss(int n) {
int now=0;
for(int i=1; i<=m; i++) {
int row=now+1;
for(; row<=n; row++)if(a[row][i])break;
if(row>n)continue;
now++;
swap(a[now],a[row]);
for(int j=1; j<=n; j++)if(now!=j&&a[j][i])a[j]^=a[now];
}
for(int i=now+1; i<=n; i++)if(a[i][m+1])return 0;
return 1;
}
bool Solve() {
for(int i=1; i<=m; i++)f[1][i].reset(),f[1][i].flip(i);
for(int i=2; i<=n+1; i++)
for(int j=1; j<=m; j++) {
f[i][j]=f[i-1][j-1]^f[i-1][j]^f[i-1][j+1]^f[i-2][j];
f[i][j][m+1]=f[i][j][m+1]^a[i-1][j];
}
int cnt=0;
for(int i=1; i<=k; i++) {
int x=Get_Int(),y=Get_Int();
a[++cnt]=f[x][y];
}
for(int i=1; i<=m; i++)a[++cnt]=f[n+1][i];
return Gauss(cnt);
}
int main() {
int T=Get_Int();
for(int t=1; t<=T; t++) {
n=Get_Int();
m=Get_Int();
k=Get_Int();
for(int i=1; i<=n; i++) {
scanf("%s",s+1);
for(int j=1; j<=m; j++)
if(s[j]=='B')a[i][j]=1;
else a[i][j]=0;
}
printf("Case #%d:\n",t);
puts(Solve()?"YES":"NO");
}
return 0;
}
本篇文章有用吗?有用还不快点击!
0%