题意:
有一个n*m的矩阵,对于每一行,如果行中有奇数个1,则置1,反之则置0,对于每一列也这样操作。
比如,行为,列为。
给出行和列的情况,让你复原这个矩阵。
如果没有这种矩阵,则输出-1。如果有多个,1多的优先输出,如果多个矩阵有相同数量的1,则输出将每一行连在一起后字典序最小的。
思路:
先把矩阵填1,看行和列的情况,根据行数列数的奇偶,可以知道每一行和每一列分别至少要几个0。
如果行中需要的0与列中需要的0相同,说明是可以直接构造的;如果行中需要的0与列中需要的0相差的个数为2的倍数,说明可以通过多加几个零来实现;如果都不是,就说明不能构造,因为要保证奇偶性相同,就一定要是2的倍数。如果要加0的话,要尽可能加在高位,这样才可以保证字典序最小。
把行和列的0变成相同以后就可以直接做了。对于某一行零的个数,从左往右往每一列里可以放的地方就放,当然对于每一行,每一列只能放一个。就这样放就可以了。
代码:
char r[55],c[55];
int rr[55],cc[55];//每一行/列各有几个0
int ans[55][55];
int main()
{
int rlen,clen;
scanf("%s",r);scanf("%s",c);
rlen=strlen(r);clen=strlen(c);//行数/列数
int r0=0,c0=0;//行/列共有几个0
//printf("%d %d\n",rlen,clen);
for(int i=0;i<rlen;i++)
{
if(clen%2==0&&r[i]=='1')
{
r0++;
rr[i]++;
}
else if(clen%2==1&&r[i]=='0')
{
r0++;
rr[i]++;
}
}
for(int i=0;i<clen;i++)
{
if(rlen%2==0&&c[i]=='1')
{
c0++;
cc[i]++;
}
else if(rlen%2==1&&c[i]=='0')
{
c0++;
cc[i]++;
}
}
//printf("%d %d\n",r0,c0);
if(r0>c0&&(r0-c0)%2!=0||c0>r0&&(c0-r0)%2!=0)
{
printf("-1\n");
return 0;
}
else
{
if(r0>c0)
{
int d=r0-c0;
for(int i=0;i<clen;i++)
{
while(cc[i]+2<=rlen)
{
cc[i]+=2;
d-=2;
if(d==0)break;
}
if(d==0)break;
}
}
else if(c0>r0)
{
int d=c0-r0;
for(int i=0;i<rlen;i++)
{
while(rr[i]+2<=clen)
{
rr[i]+=2;
d-=2;
if(d==0)break;
}
if(d==0)break;
}
}
}
//for(int i=0;i<rlen;i++)
//printf("%d ",rr[i]);
//for(int j=0;j<clen;j++)
//printf("%d ",cc[j]);
for(int i=0;i<rlen;i++)
for(int j=0;j<clen;j++)
ans[i][j]=1;
for(int i=0;i<rlen;i++)
{
if(rr[i]==0)continue;
for(int j=0;j<clen;j++)
{
if(cc[j]==0)continue;
ans[i][j]=0;
cc[j]--;rr[i]--;
if(rr[i]==0)break;
}
}
//printf("!\n");
for(int i=0;i<rlen;i++)
{
for(int j=0;j<clen;j++)
printf("%d",ans[i][j]);
printf("\n");
}
return 0;
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!