题意:

有一个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 协议 ,转载请注明出处!

HDU6376 思维+dp Previous
字符串哈希 Next