zoukankan      html  css  js  c++  java
  • 【BZOJ 4171】 4171: Rhl的游戏 (高斯消元)

    4171: Rhl的游戏

    Time Limit: 20 Sec  Memory Limit: 128 MB
    Submit: 74  Solved: 33
    [Submit][Status][Discuss]

    Description

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

    Input

    第一行一个整数T,表示T组数据。
    每组数据开始于三个整数n,m,k,分别表示格子的高度和宽度、坏掉格子的个数。接下来的n行,每行一个长度m的
    字符串,表示格子状态为'B'或'W'。最后k行,每行两个整数Xi,Yi(1≤Xi≤n,1≤Yi≤m),表示坏掉的格子。
    n,m,k<=256,T<=10

    Output

    对于每组数据,先输出一行Case #i: (1≤i≤T)
    如果可以成功,输出YES,否则输出NO。

    Sample Input

    2
    3 3 0
    WBW
    BBB
    WBW
    3 3 2
    WBW
    BBB
    WBW
    2 2
    3 2

    Sample Output

    Case #1:
    YES
    Case #2:
    NO

    HINT

    Source

    【分析】

      今天脑子真的不好,这种题既知道思路也不会打。。还要膜奥爷爷给我理思路了。。

      首先,显然是高斯消元。但当然不是每个格子都是未知量。其实只要枚举第一行,就能推出全部。

      $f[i][j]$是bitset表示的点$(i,j)$的状态,他们的异或和表示$(i,j)$这个点按还是不按。

      第一行$f[1][j]=(0,0,...1,0,0,...)$,只有第$j$位为1。

      当$(i,j)$初始为$B$,$a[i][j]=1$,否则$a[i][j]=0$。

      举个栗子:$nw$表示$(2,1)$这个点按还是不按,那么$nw$^$x1$^$x2$=$a[1][1]$ → $nw$=$x1$^$x2$^$a[1][1]$ 

      每个点都可以用第一行的$x$和$a$数组表示出来,写成$f[i][j]$即$f[2][1]=(1,1,0,0,0,0,...,a[1][1])$ 【这就是奥爷爷举的例子啦,想了一会我终于懂了

      【有时候真的不要太纠结这个是个什么方程什么的,就表示你想表示的东西就好了,毕竟异或还是很通用,很多种理解方式都可以使用高斯消元的

      常数的异或和放在$m+1$位。、

      对于损坏点$(x,y)$即 $f[x][y][1]$^$f[x][y][2]$^...$f[x][y][m+1]$=0,则$f[x][y][1]$^...$f[x][y][m]$=$f[x][y][m+1] $,看成是$m$个元的方程。

      对于最后一行,我们前面没有保证他的值是对的,所以要列$m$个方程,

      $f[n][j]$^$f[n][j-1]$ ^$f[n][j+1]$ ^$f[n-1][j]$=$a[n][j]$ 也把$m+1$项弄到右边去和$a[n][j]$异或得到新的方程。

      高斯消元判断是否有解就好了。

      注意每次求$f[i][j]$的时候是保证$(i-1,j)$这个点的状态正确。

      放弃了抄代码,终于开始自己想,自己打的时候,终于AC了。。

      事实证明,理解别人的东西还是困难的,还是要自己多多想啊!!

     1 #include<cstdio>
     2 #include<cstdlib>
     3 #include<cstring>
     4 #include<iostream>
     5 #include<algorithm>
     6 #include<bitset>
     7 using namespace std;
     8 #define Maxn 310
     9 
    10 char s[Maxn];
    11 int a[Maxn][Maxn];
    12 bitset<Maxn > f[Maxn][Maxn],w[2*Maxn];
    13 int n,m,k;
    14 
    15 bool solve()
    16 {
    17     for(int j=1;j<=m;j++)
    18     {
    19        for(int i=1;i<=n;i++) f[1][j][i]=0;
    20        f[1][j][j]=1;
    21     }
    22     for(int i=2;i<=n;i++)
    23      for(int j=1;j<=m;j++)
    24      {
    25          f[i][j]=f[i-1][j]^f[i-2][j];
    26          if(j>1) f[i][j]^=f[i-1][j-1];
    27          if(j<m) f[i][j]^=f[i-1][j+1];
    28          f[i][j][m+1]=f[i][j][m+1]^a[i-1][j];
    29      }
    30     int cnt=0;
    31     for(int i=1;i<=k;i++)
    32     {
    33         int x,y;
    34         scanf("%d%d",&x,&y);
    35         w[++cnt]=f[x][y];
    36     }
    37     w[++cnt]=f[n][1]^f[n][2]^f[n-1][1];
    38     w[cnt][m+1]=w[cnt][m+1]^a[n][1];
    39     for(int j=2;j<m;j++) w[++cnt]=f[n][j-1]^f[n][j]^f[n][j+1]^f[n-1][j],w[cnt][m+1]=w[cnt][m+1]^a[n][j];
    40     w[++cnt]=f[n][m-1]^f[n][m]^f[n-1][m];w[cnt][m+1]=w[cnt][m+1]^a[n][m];
    41     int i=1;
    42     for(int j=1;j<=m;j++)
    43     {
    44         int t=0;
    45         for(int k=i;k<=cnt;k++) if(w[k][j]) {t=k;break;}
    46         if(!t) continue;
    47         swap(w[i],w[t]);
    48         for(int k=i+1;k<=cnt;k++) if(w[k][j]) w[k]^=w[i];
    49         i++;
    50     }
    51     bool ok=1;
    52     for(int i=1;i<=cnt;i++)
    53     {
    54         bool p=1;
    55         for(int j=1;j<=m;j++) if(w[i][j]!=0) {p=0;break;}
    56         if(p&&w[i][m+1]) return 0;
    57     }
    58     return 1;
    59 }
    60 
    61 int main()
    62 {
    63     int T,kase=0;
    64     scanf("%d",&T);
    65     while(T--)
    66     {
    67         scanf("%d%d%d",&n,&m,&k);
    68         for(int i=1;i<=n;i++)
    69         {
    70             scanf("%s",s+1);
    71             for(int j=1;j<=m;j++)
    72             {
    73                 if(s[j]=='B') a[i][j]=1;
    74                 else a[i][j]=0;
    75             }
    76         }
    77         printf("Case #%d:
    ",++kase);
    78         if(solve()) printf("YES
    ");
    79         else printf("NO
    ");
    80     }
    81     return 0;
    82 }
    View Code

    2017-04-10 22:15:50

  • 相关阅读:
    编译原理语法分析程序(最左推导)
    剑指offer:02
    剑指offer:01二维数组中的查找
    pthread编译选项(命令行,codeblocks)
    学习apue的pthread synchronize之condition variables
    pthreads之joinable和detach函数
    c++指针空间大小的决定因素
    2.3.1引用
    2.2.1变量定义
    扫描PDF417崩溃的原因找到:手机摄像头分辨率低
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6691245.html
Copyright © 2011-2022 走看看