• Poj 1222 EXTENDED LIGHTS OUT


    题目大意:给你一个5*6的格子,每个格子中有灯(亮着1,暗着0),每次你可以把一个暗的点亮(或者亮的熄灭)然后它上下左右的灯也会跟着变化。最后让你把所有的灯熄灭,问你应该改变哪些灯。

     

    首先我们可以发现,如果我们对一个灯操作2次,等于啥也没干,所以呢,每个点只有可能有两种状态,操作或不操作。

    但是每个点的状态不只和自己有关,还与它周围的四个点有关,是吧?

    所以相当于对于每个点解一个方程:

      之前的状态  XOR  自己变没变  XOR  周围的四个点变没变  = 目标状态  (暗着)

    稍稍变动一下,两边同时XOR之前的状态。

       自己变没变  XOR  周围的四个点变没变  = 之前的状态 

    然后把所有点的异或方程合在一起,就得到了一个异或方程组。

    解开这个方程组就大事告成了!

    为了咱们解方程比较简单,我们可以在这个点的异或方程中,把影响到这个点的点的系数a记为1,不影响的记为0,将每个点是否操作作为所求的变量x1..n(n为点数),最终状态b作为方程的右边。

    a1*x1  xor  a2*x2  xor  a3*x3  xor ... xor  an*xn = b

    其中a,x,b的取值都是1或0(ai的值表示是否对这个点有影响,b的值表示最后是否亮着,xi的值表示是否对点i进行操作),考虑完单个点的情况,再将所有点的方程加入:

    a11*x1  xor  a12*x2  xor  a13*x3  xor ... xor  a1n*xn = b1

    a21*x1  xor  a22*x2  xor  a23*x3  xor ... xor  a2n*xn = b2

    ... ... ... ...

    an1*x1  xor  an2*x2  xor  an3*x3  xor ... xor  ann*xn = bn

    从而得到一个n*n的矩阵,再加上一列最终状态构成的列向量。

    a11  a12  a13 ... a1n   b1

    a21  a22  a23 ... a2n   b2

    ... ... ... ...

    an1  an2  an3 ... ann   bn

    然后就是高斯消元时间啦!!——>见【高斯消元】

    /*
        Poj 1222
        Author: Robert_Yuan
        Memory: 364K
        Time: 0MS
    */
    #include<cstdio>
    #include<cstring>
    
    using namespace std;
    
    #define maxn 32
    
    int n,m;
    int x[maxn];
    int a[maxn][maxn];
    int w[maxn][maxn];                    //w[i][j] 表示 i,j是否能互相影响 
    
    void swap(int i,int j){
        int t;
        for(int k=i;k<=m*n+1;k++)
            t=w[i][k],w[i][k]=w[j][k],w[j][k]=t;
    }
    
    void Xor(int i,int j){
        for(int k=i;k<=m*n+1;k++)
            w[j][k]=w[j][k]^w[i][k];
    }
    
    void print(){    
        for(int i=1;i<=n*m;i++){
            for(int j=1;j<=m*n+1;j++)
                printf("%d ",w[i][j]);
            printf("
    ");
        }    
        printf("
    
    ");
    }
    
    void gauss(){                        //高斯消元 解 异或方程 
        //print();
        
        for(int i=1;i<=m*n;i++){
            bool find=false;
            for(int j=i;j<=m*n;j++)
                if(w[j][i]){             
                    swap(i,j);find=true;break;
                }
            if(!find)    continue;
            for(int j=i+1;j<=m*n;j++)
                if(w[j][i])
                    Xor(i,j);
        }
        
        //print();
        
        for(int i=m*n;i>=1;i--){
            x[i]=w[i][m*n+1];
            if(!x[i])    continue;
            for(int j=i-1;j>=1;j--)
                if(w[j][i])
                    w[j][m*n+1]^=x[i];
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++)
                printf("%d ",x[(i-1)*m+j]);
            printf("
    ");
        }
    }
    
    void prework(){
        n=5,m=6;
        memset(w,0,sizeof(w));
        for(int i=1;i<=n;i++)    
            for(int j=1;j<=m;j++)
                scanf("%d",&a[i][j]),w[(i-1)*m+j][m*n+1]=a[i][j];
        for(int i=1;i<=n;i++)
            for(int j=1;j<=m;j++){
                w[(i-1)*m+j][(i-1)*m+j]=1;                //自己和上下左右是对自己有影响的点 
                if(j!=1) w[(i-1)*m+j][(i-1)*m+j-1]=1;
                if(j!=m) w[(i-1)*m+j][(i-1)*m+j+1]=1;
                if(i!=n) w[(i-1)*m+j][i*m+j]=1;
                if(i!=1) w[(i-1)*m+j][(i-2)*m+j]=1;
            }
    }
    
    int main(){
    #ifndef ONLINE_JUDGE
        freopen("x.in","r",stdin);
        freopen("x.out","w",stdout);
    #endif
        int T,cnt=0;
        scanf("%d",&T);
        while(T--){
            prework();
            printf("PUZZLE #%d
    ",++cnt);
            gauss();
        }
    }
    View Code

    AC通道—> http://poj.org/problem?id=1222

  • 相关阅读:
    (转)基于REST架构的Web Service设计
    WPF 简易的喷泉效果
    C# 取Visio模型信息的简易方法
    WPF TextBox按字节长度限制输入
    NPOI导出WPF DataGrid控件显示数据
    WPF--TextBlock的ToolTip附加属性
    【转】WPF 从FlowDocument中找到Hyperlink
    WPF 初学VisifireChart
    WPF 简易进度条效果
    WPF 简易的跑马灯效果
  • 原文地址:https://www.cnblogs.com/Robert-Yuan/p/4617170.html
Copyright © 2020-2023  润新知