• 【JZOJ6236】【20190628】启程的日子


    题目

    给你一个(n imes m)的01矩阵

    你需要用一些矩阵加减出这个矩阵

    求最少的步数,并输出方案

    需要满足构造出的01矩阵是一个四联通块

    $ n , m le 500 $

    题解

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

    • 如何用三步构造一个$ n le m , m ge 3$的矩阵

      矩阵A:

      第1列为1,奇数行为1,偶数行为原矩阵

      矩阵B:

      第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
    ",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
    ",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;
    }
    
  • 相关阅读:
    求超大文件上传方案( vue )
    求超大文件上传方案( csharp )
    求超大文件上传方案( c# )
    求超大文件上传方案( .net )
    求超大文件上传方案( asp.net )
    求超大文件上传方案( php )
    求超大文件上传方案( jsp )
    用浏览器 实现断点续传 (HTTP)
    shuffle() 函数
    no.random.randn
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/11147544.html
Copyright © 2020-2023  润新知