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

  

posted @ 2016-09-22 20:40  Claris  阅读(392)  评论(0编辑  收藏  举报