参考博客:
https://blog.csdn.net/a54665sdgf/article/details/81584632
题目链接:
https://vjudge.net/contest/265795#problem/H
题意:
给出矩阵每行每列的特点,1代表这一行或列有奇数个1,0代表这一行或列有偶数个1,让你恢复原矩阵,并且1尽可能多,如果1数量一样,要求使0尽可能靠左上角(转化成的2进制数更小)。
思路:
既然要求1尽量多,不妨初始化时全部置成1,对于全部置成1的矩阵,它对应的题目描述矩阵就是 两个全是0的串(这时需要注意,如果某行某列是奇数个1,我们也是将它看作0了,若要等价对待,需要将原川对应的值反转)。接下来两个是对两个01串的处理,在上面取一个1,下面也取一个1,将全是1的矩阵中的对应位置的1改成0,你会发现,对于新的矩阵,你所选择的01矩阵的两个1全变成0了,这是因为,一个位置的01变动,会影响两个01串对应的行和列的值。为了得到尽可能多的1,我们需要对原01串进行两两配对,而且为了得到的二进制数尽可能的少,我们需要优先将靠左的1进行配对(对应矩阵就是左上角的位置了)。
这样,如果1恰好两两配对,那么皆大欢喜。
否则,会出现两种情况:上面多1,或者下面多1
再详细点分,多出来的1可能有奇数个,也可能有偶数个
如果多出来偶数个1 ,举例来说
给出01串是:
1100
0000
这时候,如果把(1,0)位置的数变成1
串就变成
0100
1000
下一次,就可以匹配了。依次类推
需要注意的是,一定要将第一个变成0,因为要满足二进制最小的要求。
这样,变一个,再配对。需要什么条件能配成功呢?
需要有偶数个1!!!(奇数个1即是不满足条件的)
可以想象,如果给出的01串如果只有一个1,那么无论如何都得不到满足条件的矩阵,以为一个变,同时影响行和列。
#include <bits/stdc++.h>
using namespace std;
const int maxn = 60;
int a[maxn][maxn];
string r,c;
int n,m;
bool judge()
{
n = r.length();
m = c.length();
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
a[i][j] = 1;
if(m&1)
{
for(int i = 0; i < n; i++)
{
r[i] = r[i] == '0' ? '1' : '0';
}
}
if(n&1)
{
for(int i = 0 ; i < m; i++)
c[i] = c[i] == '0' ? '1' : '0';
}
int cntrow = count(r.begin(),r.end(),'1');
int cntcol = count(c.begin(),c.end(),'1');
if((cntcol + cntrow)&1)
return 0;
for(int i = 0; cntrow > cntcol ; i++)
{
if(r[i] == '1')
{
r[i] = '0';
a[i][0] = 0;
cntrow--;
}
}
for(int i = 0; cntcol > cntrow ; i++)
{
if(c[i] == '1')
{
c[i] ='0';
a[0][i] = 0;
cntcol--;
}
}
for(int i = 0, j =0 ; i < n; i++)
{
if(r[i] =='1')
{
while(c[j]=='0')j++;
a[i][j] = 0;
j++;
}
}
return 1;
}
int main()
{
cin>>r>>c;
if(judge())
{
for(int i = 0; i < n ; i++)
{
for(int j = 0; j < m; j++)
cout<<a[i][j];
cout<<endl;
}
}
else
{
cout<<-1<<endl;
}
return 0;
}
再附上队友的代码,原理一样
#include <bits/stdc++.h>
using namespace std;
char s1[55],s2[55];
int a[55],b[55];
char s[55][55];
int main()
{
memset(s,'1',sizeof(s));
scanf("%s",s1);
scanf("%s",s2);
int cnt1=1,cnt2=1;
char x,y;
if(strlen(s2)&1) x='1';
else x='0';
if(strlen(s1)&1) y='1';
else y='0';
for(int i=0;s1[i]!=0;++i){
if(s1[i]!=x) a[cnt1++]=i+1;;
}
for(int i=0;s2[i]!=0;++i){
if(s2[i]!=y) b[cnt2++]=i+1;
}
int cnt=cnt1+cnt2;
if(cnt&1){
printf("-1\n");
return 0;
}
while(cnt1<cnt2) a[cnt1++]=1;
while(cnt2<cnt1) b[cnt2++]=1;
sort(a+1,a+cnt1);sort(b+1,b+cnt2);
for(int i=1;i<cnt1;++i){
s[a[i]][b[i]]='0';
}
for(int i=1;i<=strlen(s1);++i){
for(int j=1;j<=strlen(s2);++j){
printf("%c",s[i][j]);
}
putchar('\n');
}
return 0;
}