BZOJ4171 : Rhl的游戏

时间:2023-03-09 23:55:51
BZOJ4171 : Rhl的游戏

把第一行每个位置设成未知量,对于之后每一行,都可以用第一行的未知量线性表示。

那么只需要加上最后一行的$m$个方程,对于不能按的那$k$个位置也列出对应的方程。

用高斯消元判断是否有解即可,时间复杂度$O(\frac{n^3}{64})$。

#include<cstdio>
#include<algorithm>
#include<bitset>
#define N 260
using namespace std;
int T,C,n,m,k,cnt,i,j,t,x,y;char s[N][N];bitset<N>f[N][N],a[N*2];
bool solve(){
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=n;i++)scanf("%s",s[i]+1);
for(j=1;j<=m;j++)f[1][j].reset(),f[1][j][j]=1;
for(i=2;i<=n;i++)for(j=1;j<=m;j++){
f[i][j]=f[i-1][j]^f[i-2][j];
if(j>1)f[i][j]^=f[i-1][j-1];
if(j<m)f[i][j]^=f[i-1][j+1];
if(s[i-1][j]=='B')if(f[i][j][m+1])f[i][j][m+1]=0;else f[i][j][m+1]=1;
}
cnt=0;
for(j=1;j<=m;j++){
a[++cnt]=f[n][j];
if(j>1)a[cnt]^=f[n][j-1];
if(j<m)a[cnt]^=f[n][j+1];
if(n>1)a[cnt]^=f[n-1][j];
if(s[n][j]=='B')if(a[cnt][m+1])a[cnt][m+1]=0;else a[cnt][m+1]=1;
}
while(k--)scanf("%d%d",&x,&y),a[++cnt]=f[x][y];
for(i=j=1;i<=m;i++){
for(t=0,k=j;k<=cnt;k++)if(a[k][i]){t=k;break;}
if(!t)continue;
swap(a[j],a[t]);
for(k=j+1;k<=cnt;k++)if(a[k][i])a[k]^=a[j];
j++;
}
for(i=1;i<=cnt;i++){
for(j=1;j<=m;j++)if(a[i][j])break;
if(j>m&&a[i][m+1])return 0;
}
return 1;
}
int main(){
scanf("%d",&T);
for(C=1;C<=T;C++)printf("Case #%d:\n",C),puts(solve()?"YES":"NO");
return 0;
}