POJ 1222 高斯消元

题意:
给你一个5*6的矩阵,你可以在任意位置对这个位置及其上下左右(如果有的话)进行xor【读作:叉欧二 ( :-D) 】操作,求解在哪些地方进行。
思路:
0. 一个显而易见就超时的方法(2^30),枚举第i个灯是开是关 但为第一种方法提供了思路
1.好像可以枚举第一行,然后通过递推算中间的几行,判断最后一行成不成立。
2.高斯消元,30个异或方程。

自己写得第一发高斯消元(虽然代码比较冗长,但自己yy出来很鸡冻)

// by Sirius_Ren
#include <cstdio>
#include <cstring>
using namespace std;
int eli[35][35],ans[31],x[32],cases,tot;
void solve(){
    for(int i=1;i<=30;i++)
    if(~ans[i]&&eli[tot][i])eli[tot][31]=(eli[tot][31]+ans[i])%2;
    for(int i=1;i<=30;i++)
        if(eli[tot][i]&&ans[i]==-1)ans[i]=eli[tot][31];
    tot--;
}
int main(){
    scanf("%d",&cases);
    for(int ii=1;ii<=cases;ii++){
        memset(ans,-1,sizeof(ans));
        memset(x,0,sizeof(x));
        memset(eli,0,sizeof(eli));
        tot=30;
        for(int i=1;i<=30;i++)
            scanf("%d",&eli[i][31]);
        for(int i=1;i<=30;i++){
            eli[i][i]=1;
            if(i-6>0)eli[i][i-6]=1;
            if(i+6<=30)eli[i][i+6]=1;
            if(i%6)eli[i][i+1]=1;
            if(i%6!=1)eli[i][i-1]=1;
        }
        for(int i=1;i<=29;i++)
            for(int l=1;l<=30;l++)
            if(eli[i][l]&&!x[l]){
                x[l]=i;
                for(int j=i+1;j<=30;j++)
                    if(eli[j][l])
                        for(int k=1;k<=31;k++)
                            eli[j][k]^=eli[i][k];
                break;
            }
        solve();
        for(int i=29;i>=1;i--)
            for(int j=1;j<=30;j++)
                if(x[j]==i){
                    solve();
                    break;
                }
        printf("PUZZLE #%d\n",ii);
        for(int i=1;i<=30;i++){
            if(i%6)
            printf("%d ",ans[i]);
            else printf("%d\n",ans[i]);
        }
    }
}
posted @ 2016-05-15 18:03  SiriusRen  阅读(162)  评论(0编辑  收藏  举报