【JZOJ6236】【20190628】啓程的日子

題目

給你一個\(n \times m\)的01矩陣c++

你須要用一些矩陣加減出這個矩陣spa

求最少的步數,並輸出方案code

須要知足構造出的01矩陣是一個四聯通塊it

$ n ,  m \le 500 $class

題解

  • 答案=0/1/2時特判,n,m<=2時特判im

  • 如何用三步構造一個$ n \le m  , m \ge 3$的矩陣di

    矩陣A:vi

    第1列爲1,奇數行爲1,偶數行爲原矩陣co

    矩陣B:time

    第n列爲1,偶數行爲1,奇數行爲原矩陣

    矩陣C:

    第一列和最後一列爲原矩陣取反,其它爲0

    用A+B-C便可構造

Code

#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=510;
int n,m,a[N][N],rev,b[N][N],f[N*N],tot,vis[N*N],id[N][N],st1[N*N],t1,st2[N*N],t2;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
vector<int>vec[N*N];
char s[N];
void print(){
    if(!rev){
        for(int i=1;i<=n;++i,puts(""))
        for(int j=1;j<=m;++j)printf("%d",b[i][j]);
    }else{
        for(int i=1;i<=m;++i,puts(""))
        for(int j=1;j<=n;++j)printf("%d",b[j][i]);
    }
}
int find(int x){return f[x]==x?x:f[x]=find(f[x]);}
void uni(int x,int y){
    if(!x||!y)return;
    int fx=find(x),fy=find(y);
    if(fx==fy)return;
    f[fx]=fy;
}
int main(){
    freopen("bitbit.in","r",stdin);
    freopen("bitbit.out","w",stdout);
    scanf("%d%d",&n,&m);
    int ex=0;
    for(int i=1;i<=n;++i){
        scanf("%s",s+1);
        for(int j=1;j<=m;++j)a[i][j]=s[j]=='1',ex|=a[i][j];
    }
    if(!ex)puts("0"),exit(0);
    if(n>m){
        for(int i=1;i<=n;++i)
        for(int j=1;j<=i&&j<=m;++j){
            swap(a[i][j],a[j][i]);
        }
        swap(n,m);rev^=1;
    }
    if(n==1){
        int ans=0;
        for(int i=1;i<=m;++i)if(a[1][i]&&a[1][i]!=a[1][i-1])ans++;
        printf("%d\n",ans);
        for(int i=1;i<=m;++i)if(a[1][i]){
            puts("+");
            for(int j=1;j<i;++j)b[1][j]=0;
            for(;i<=m&&a[1][i];++i)b[1][i]=1;
            for(int j=i--;j<=m;++j)b[1][j]=0;
            print();
        }
        return 0;
    }//n=1||m=1
    if(n==2&&m==2){
        int tmp=a[1][1]+a[1][2]+a[2][1]+a[2][2];
        if(tmp==2&&max(a[1][1]+a[2][2],a[1][2]+a[2][1])==2){
            puts("2");
            for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)if(a[i][j]){
                puts("+");
                for(int i1=1;i1<=n;++i1)
                for(int j1=1;j1<=m;++j1)
                    b[i1][j1]=(i1==i&&j1==j);
                print();
            }
            return 0;
        }//ans=2
        puts("1");
        puts("+");
        for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)b[i][j]=a[i][j];
        print();//ans=1;
        return 0;
    }//n=2&&m=2
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)id[i][j]=++tot,f[tot]=tot;
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j){
        if(a[i-1][j]==a[i][j])uni(id[i-1][j],id[i][j]);
        if(a[i][j-1]==a[i][j])uni(id[i][j-1],id[i][j]);
    }
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j){
        vec[find(id[i][j])].pb(id[i][j]);
        if(f[id[i][j]]!=id[i][j])continue;
        if(a[i][j])st1[++t1]=id[i][j];
        else st2[++t2]=id[i][j];
    }
    if(t1<=2){
        printf("%d\n",t1);
        for(int I=1;I<=t1;++I){
            puts("+");
            for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)b[i][j]=(f[id[i][j]]==st1[I]);
            print();
        }
        return 0;
    }//ans=1,ans=2(1)
    for(int I=1;I<=t2;++I){
        for(int pos : vec[st2[I]]){
            int x=(pos-1)/m+1,y=(pos-1)%m+1;
            for(int k=0;k<4;++k){
                int nx=x+dx[k],ny=y+dy[k];
                if(id[nx][ny])vis[f[id[nx][ny]]]=I;
            }
        }
        int fg=1;for(int i=1;i<=t1;++i)if(vis[st1[i]]!=I){fg=0;break;}
        if(fg){
            int now=st2[I];
            puts("2");
            puts("+");
            for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)b[i][j]=(a[i][j])||(f[id[i][j]]==now);
            print();
            puts("-");
            for(int i=1;i<=n;++i)
            for(int j=1;j<=m;++j)b[i][j]=(f[id[i][j]]==now);
            print();
            return 0;
        }
    }//ans=2(2);
    puts("3");
    puts("+");
    for(int i=1;i<=n;++i)
    for(int j=1;j<m;++j)b[i][j]=(j==1)||(i&1)||(a[i][j]);
    for(int i=1;i<=n;++i)b[i][m]=0;
    print();
    puts("+");
    for(int i=1;i<=n;++i)
    for(int j=2;j<=m;++j)b[i][j]=(j==m)||(!(i&1))||(a[i][j]);
    for(int i=1;i<=n;++i)b[i][1]=0;
    print();
    puts("-");
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)b[i][j]=(j!=1&&j!=m)||(!a[i][j]);
    print();//ans=3
    return 0;
}
相關文章
相關標籤/搜索