题目大意
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; }
|