HYSBZ/BZOJ 3503 和谐矩阵 - 高斯约当消元异或方程

题目描述

Solution 1:

把矩阵中的每一个元素看作未知数,根据元素之间的互相影响列方程,方程大小为 (n*m,n*m)。如果有不定解怎么办呢?

1. dfs暴力枚举每一个不定解。肯定要TLE

2. 在每行确定解的时候,强制性设定这行的所有不定解为1 ,继续回代,直到出答案。 好像数据挺水,O((nm)3)勉强能过。

1.代码,但要T

#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 1600

int dir[10][3]={{0,0},{0,1},{0,-1},{1,0},{-1,0}};
int n,m;
int a[MAXN+10][MAXN+10],id[MAXN+10][MAXN+10],x[MAXN+10],p;

void Structure()
{
    int x,y;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            id[i][j]=(i-1)*m+j;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=0;k<5;k++){
                x=i+dir[k][0],y=j+dir[k][1];
                if(x>=1&&x<=n&&y>=1&&y<=m)
                    a[id[x][y]][id[i][j]]=1;
            }
}
void GJ_elimination(int equ,int var,int &row,int &col)
{
    int mx;
    for(row=col=1;row<=equ&&col<=var;row++,col++){
        mx=row;
        for(int i=row+1;i<=equ;i++){
            if(a[i][col]>a[mx][col])
                mx=i;
            if(a[mx][col]==1)
                break;
        }
        if(mx!=row)
            swap(a[row],a[mx]);
        if(a[row][col]==0){ //本题有唯一解,这句if可以不要
            row--;
            continue;
        }
        for(int i=1;i<=equ;i++){
            if(i==row||a[i][col]==0)
                continue;
            for(int j=var+1;j>=1;j--)
                a[i][j]^=a[row][j];
        }
    }
}
int GJ_Judge(int equ,int var,int row,int col)
{
    if(row<=var)
        return row;
    for(int i=row-1;i>=1;i--)
        x[i]=a[i][var+1];
    return 0;
}
int Gauss_Jordan(int equ,int var)
{
    int row,col;
    GJ_elimination(equ,var,row,col);
    return GJ_Judge(equ,var,row,col);
}
void print()
{
    for(int i=1;i<=n*m;i++){
        printf("%d",x[i]);
        if(i%m==0) printf("\n");
        else printf(" ");
    }
}
bool check()
{
    int cnt=0,tmp;
    for(int i=p-1;i>=1;i--){
        tmp=0;
        for(int j=i+1;j<=n*m;j++)
            if(a[i][j])
                tmp^=x[j];
        x[i]=a[i][n*m+1]^tmp;
        if(!x[i]) cnt++;
    }
    for(int i=p;i<=n*m;i++)
        if(!x[i]) cnt++;
    if(cnt==n*m) return false;
    else return true;
}
void dfs(int u)
{
    if(u>n*m){
        if(check()){
            print();
            exit(0);
        }
        return ;
    }
    x[u]=1; dfs(u+1);
    x[u]=0; dfs(u+1);
}
int main()
{
    scanf("%d%d",&n,&m);
    Structure();
    p=Gauss_Jordan(n*m,n*m);
    if(!p)
        print();
    else
        dfs(p);
}

2.代码 by Liu Junhao 这是他关于这道题的blog


void gauss_jordan(){
    int row,col,i,j,cnt;
    for(row=col=1;row<=equ&&col<=var;row++,col++){
        if(!a[row][col])
            for(i=row+1;i<=equ;i++)
                if(a[i][col]){
                    swap(a[row],a[i]);
                    break;
                }
        if(!a[row][col]){
            row--;
            continue;
        }
        for(i=1;i<=equ;i++)
            if(i!=row&&a[i][col])
                for(j=var+1;j>=col;j--)
                    a[i][j]^=a[row][j];
    }
    row--;
    for(i=row;i;i--){
        cnt=0;
        for(j=i;j<=var;j++)
            if(a[i][j]){
                if(!vis[j])
                    cnt++;
                else
                    a[i][var+1]^=x[j],a[i][j]=0;
            }
        for(j=i;j<=var;j++)
            if(a[i][j]){
                if(--cnt)
                    x[j]=1,a[i][var+1]^=1;
                else
                    x[j]=a[i][var+1];
                vis[j]=1;
            }
    }
}
void print(){
    int i,j;
    for(i=1;i<=n;i++){
        for(j=1;j<=m;j++)
            printf("%d ",x[(i-1)*m+j]);
        puts("");
    }
}
int main()
{
    read();
    gauss_jordan();
    print();
}

Solution 2:

将矩阵第一行的m个元素看作未知数,记为x1 ~ xm,由元素之间的互相影响可以推出其后的每个元素关于x1 ~ xm 的关系式,最后由剩下的m个影响关系得到m个关于x1 ~ xm 的方程,用高斯消元求解,O(m3)的复杂度。

对于不定解的处理仍然有solution 1 中的两种方案,但方案1可用了,不会再超时,而且较solution快了不知多少倍。

可惜solution 2的代码太长,把Special Judge()去掉的话会好看一些

#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 40
int dir[10][3]={{-2,0},{-1,0},{-1,-1},{-1,1}};
int dir2[10][3]={{0,0},{0,1},{0,-1},{-1,0}};

int n,m,a[MAXN+10][MAXN+10],x[MAXN+10];
int p[MAXN+10][MAXN+10][MAXN+10],cntx,ans[MAXN+10][MAXN+10];

void print();

void Represent()
{
    int x,y;
    for(int j=1;j<=m;j++)
        p[1][j][j]=1;
    for(int i=2;i<=n;i++){
        for(int j=1;j<=m;j++)
            for(int k=0;k<4;k++){
                x=i+dir[k][0],y=j+dir[k][1];
                if(!(x>=1&&x<=n&&y>=1&&y<=m))
                    continue;
                for(int t=1;t<=m;t++)
                    p[i][j][t]^=p[x][y][t];
            }
    }
}
void Structure()
{
    int x,y;
    for(int j=1;j<=m;j++){
        for(int k=0;k<4;k++){
            x=n+dir2[k][0],y=j+dir2[k][1];
            if(!(x>=1&&x<=n&&y>=1&&y<=m))
                continue;
            for(int t=1;t<=m;t++)
                a[j][t]^=p[x][y][t];
        }
    }
}
void GJ_elimination(int equ,int var,int &row,int &col)
{
    int mx;
    for(row=col=1;row<=equ&&col<=var;row++,col++){
        mx=row;
        for(int i=row+1;i<=equ;i++){
            if(a[i][col]>a[mx][col])
                mx=i;
            if(a[mx][col]==1)
                break;
        }
        if(mx!=row)
            swap(a[mx],a[row]);
        if(a[row][col]==0){
            row--;
            continue;
        }
        for(int i=1;i<=equ;i++){
            if(i==row||a[i][col]==0)
                continue;
            for(int j=1;j<=var+1;j++)
                a[i][j]^=a[row][j];
        }
    }
}
int Gauss_Jordan(int equ,int var)
{
    int row,col;
    GJ_elimination(equ,var,row,col);
    if(row<=var) return var-row+1;
    else return 0;
}
bool Judge()
{
    int cnt0=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            for(int k=1;k<=m;k++)
                if(p[i][j][k])
                    ans[i][j]^=x[k];
            if(!ans[i][j])
                cnt0++;
        }
    if(cnt0==n*m) return false;
    else return true;
}
bool check(int cntx)
{
    int tmp;
    for(int i=m-cntx;i>=1;i--){
        tmp=0;
        for(int j=i+1;j<=m;j++)
            if(a[i][j])
                tmp^=x[j];
        x[i]=a[i][m+1]^tmp;
    }
    return Judge();
}
bool SpecialJudge()
{
    int dr[10][6]={{0,0},{1,0},{-1,0},{0,1},{0,-1}};
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            int tmp=0;
            for(int k=0;k<5;k++){
                int x=i+dr[k][0],y=j+dr[k][1];
                if(x>=1&&x<=n&&y>=1&&y<=m){
                    tmp^=ans[x][y];
                }
            }
            if(tmp){
                printf("%d %d\n",i,j);
                return false;
            }
        }
    }
    return true;
}
void print()
{
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++)
            printf("%d ",ans[i][j]);
        puts("");
    }
    /*if(SpecialJudge())
        printf("Right\n");
    else
        printf("Wrong\n");*/
}
void dfs(int u)
{
    if(u>m){
        if(check(cntx)){
            print();
            exit(0);
        }
        return ;
    }
    x[u]=1; dfs(u+1);
    x[u]=0; dfs(u+1);
}
int main()
{
    scanf("%d%d",&n,&m);
    Represent();
    Structure();
    cntx=Gauss_Jordan(m,m);
    if(cntx)
        dfs(m-cntx+1);
    else{
        for(int i=1;i<=m;i++)
            x[i]=a[i][m+1];
        print();
    }
    return 0;
}
posted @ 2016-02-01 18:55  KatarinaYuan  阅读(151)  评论(0编辑  收藏  举报