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; }